1 实验题目

计算π的一个有趣方法是使用一个称为Monte Carlo的技术,这种技术涉及随机。该技术工作如下:假设有一个圆,它内嵌一个正方形,如下图所示。

首先,通过(x,y)坐标生成一系列的随机点。这些点应在正方形内。在这些随机产生的点中,有的会落在圆内。接着,根据下面公式,估算π。

π= 4✖️(圆内的点数)/(总点数)

(1)请编写一个多线程版的算法,它创建一组子线程,每个子线程产生一组随机点,并确定点是否落在圆内。每个子线程更新所有落在园内的点的全局计数。当所有子线程计算完毕后,使用父线程计算π。(通过采用互斥锁,保护对共享全局变量的更新)?

(2)针对题目(1)请考虑一下,该怎样来提高计算π的性能(速度)?请实现相关的思想或算法的代码,并给出分析说明和实验数据证明!

2蒙特卡洛方法介绍

百度百科:百度百科

蒙特卡洛法,也称为统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法。是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。

3分析思路

①蒙特卡洛的本质是统计方法,所以必然要获取大量的数据才能得到较为精确的圆周率,

②在计算π的公式中,S=πrr,所以π=S/(rr),当r=1时,π此时等于S

③可以假设圆的半径为1,并且此时圆的外接正方形为22=4,设圆心位于坐标轴(0,0)④通过产生大量位[-1,1]的随机数坐标(x,y),即-1<=x<=1,-1<=y<=1,若x^2+y^2<=1,则某个随机点落在圆内,否则落在圆外

⑤最终我们所求的圆周率π即为随机数的个数和/落在园内的随机数和。

⑥通过使用互斥锁来保证结果的正确性

4代码实现

4.1 安装插件

POSIX下开发多线程主要依赖的就是Pthread。使用它需要包含头文件#include。因为这个库在Pthread之中,在编译的时候需要加上参数:-lpthread.

4.1.1

在终端输入命令

sudo apt-get install glibc-doc

然后输入密码

sudo apt-get install manpages-posix manpages-posix-dev

然后输入密码

自行百度linux下载vim(如果有就不用下载了)

4.1.2

新建一个文件夹tt

在文件夹中右击打开终端

输入

vi test2.c

按 i 进入编辑模式

4.2代码编写

#include

#include

#include

#include

#include

#define random_1(a,b) ((rand()%(b-a))+a) //随机值将含a不含b

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int value = 0;

long double valid=0,all=999999;//初始化有效点为0,总点数为999999

long double pi=0;

void* fun(void* arg) {

pthread_mutex_lock(&mutex);

long double x,y;//定义坐标x,y

int i=1;

srand((double)time(NULL)); //设置随机数种子,防止每次产生的随机数相同

for(i=1;i<=999999;i++)

{

//获取x,y的随机值,0<=x<100000,0<=y<100000

x=random_1(0,100000);

y=random_1(0,100000);

if(x*x+y*y<=10000000000)

valid++;

}

pthread_mutex_unlock(&mutex);

return (void*)0;

}

//主函数

int main()

{

clock_t start, end;

start = clock(); //读取程序开始运行的时间

pthread_t theradId1, threadId2;//定义两个子线程

int error;//定义线程返回值error,若是成功建立线程返回0,否则返回错误的编号

pthread_mutex_init(&mutex, NULL);//互斥锁初始化

error = pthread_create(&theradId1, NULL, fun, NULL);

sleep(2);//用sleep()控制子线程的不同并发过程

if(error) {

printf("Thread1 creat failed!\n");

exit(1);

}

error = pthread_create(&threadId2, NULL, fun, NULL);

if(error) {

printf("Thread2 creat failed!\n");

exit(1);

}

end = clock(); //记录结束时间

pi=valid/999999*4;

printf("valid的值为: %Lf\n",valid);

printf("总的点数的值为999999\n");

printf("π的值为: %Lf\n",pi);

double seconds =(double)(end - start)/CLOCKS_PER_SEC*1000;

printf("Use time is: %.3fms\n", seconds);

//进程锁销毁

pthread_mutex_destroy(&mutex);

return 0;

}

4.3执行代码

按 ESC 键 然后输入":"(冒号),再输入"wq",回车

输入

gcc -o test test2.c -lpthread

再输入

./test

显示结果

当选取的点数较少是,例如200个,此时结果并不准确

当选取的总点数较多时,例如9999999个,结果相对更接近π

//可修改部分参数使结果更精确(多次测量求平均值)

5遇到的问题及解决方法

5.1随机数的获取问题

通过rand()函数可以获取整数,如果半径控制在0~1的话,可能没办法实现随机小数获取,可以假设半径为100000(double型),当x,y的平方和小于10000000000时就可以说明在园内,否则在圆外

5.2随机数种子问题

如果不设置随机数种子,则每次获得的随机数在1s内相同,无法生成真正的随机数

6实验改进:OpenMP方法

6.1 OpenMP方法介绍

Open Multi-Processing的缩写,是一个应用程序接口(API),可用于显式指导多线程、共享内存的并行性。

在项目程序已经完成好的情况下不需要大幅度的修改源代码,只需要加上专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。当选择忽略这些pragma,或者编译器不支持OpenMp时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。OpenMP提供的这种对于并行描述的高层抽象降低了并行编程的难度和复杂度,这样程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。对基于数据分集的多线程程序设计,OpenMP是一个很好的选择。

OpenMP支持的语言包括C/C++、Fortran;而支持OpenMP的编译器VS、gcc、clang等都行。可移植性也很好:Unix/Linux和Windows

6.2 编程实现

打开终端输入

vi test2_2.c

按 i 进入编辑模式

输入代码

#include

#include

#include

#include

#include

#include

#define random_1(a,b) ((rand()%(b-a))+a) //随机值将含a不含b

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int value = 0;

long double valid=0,all=999999;//初始化有效点为0,总点数为999999

long double pi=0;

//void* fun(void* arg) {

void fun(){

// pthread_mutex_lock(&mutex);

long double x,y;//定义坐标x,y

int i=1;

srand((double)time(NULL)); //设置随机数种子,防止每次产生的随机数相同

for(i=1;i<=999999;i++)

{

//获取x,y的随机值,0<=x<100000,0<=y<100000

x=random_1(0,100000);

y=random_1(0,100000);

if(x*x+y*y<=10000000000)

#pragma omp crirical //OpenMP并行编排支持

{

valid++;

}

}

// pthread_mutex_unlock(&mutex);

// return (void*)0;

}

//主函数

int main()

{

clock_t start, end;

start = clock(); //读取程序开始运行的时间

fun();

end = clock(); //记录结束时间

pi=valid/999999*4;

printf("valid的值为: %Lf\n",valid);

printf("总的点数的值为999999\n");

printf("π的值为: %Lf\n",pi);

double seconds =(double)(end - start)/CLOCKS_PER_SEC*1000;

printf("Use time is: %.3fms\n", seconds);

//进程锁销毁

pthread_mutex_destroy(&mutex);

return 0;

}

按Esc 再输入“:”,输入“wq”,回车

在终端输入

gcc -o test test2_2.c -fopenmp

再输入

./test

得到结果

和之前的普通互斥锁使用,在总点数相同的前提下(都为9999999个)可以明显看出使用OpenMP方法运行时间短很多

8参考内容

7源代码下载

链接密码: qsp3

仅供参考,请不要直接复制,还有很多不足之处,希望能共同进步,欢迎批评指正!

linux多线程编程实现圆周率,linux环境下使用Monte Carlo计算π相关推荐

  1. Linux系统编程及应用——ubuntu环境下

    Linux系统编程及应用--ubuntu环境下 程序由业务逻辑和系统访问两部分构成的.其中,业务逻辑是根据业务需求,按照设计好的逻辑规则,处理信息,与系统(平台)无关的:而系统访问则是利用操作系统所提 ...

  2. linux多线程编程实验报告,Linux多线程编程

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 使用pthread_create函数创建线程.1 2 3 4 5 6 7 8int (pthread_t *__rest ...

  3. linux查询某域线程是否满了,Linux多线程编程的时候怎么查看一个进程中的某个线程是否存活...

    pthread_kill: 别被名字吓到,pthread_kill可不是kill,而是向线程发送signal.还记得signal吗,大部分signal的默认动作是终止进程的运行,所以,我们才要用sig ...

  4. Linux多线程编程-互斥锁

    互斥锁 多线程编程中,(多线程编程)可以用互斥锁(也称互斥量)可以用来保护关键代码段,以确保其独占式的访问,这有点像二进制信号量.POSIX互斥锁相关函数主要有以下5个: #include <p ...

  5. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

  6. Linux 多线程编程(实现生产者消费者模型)

    Linux 多线程编程 线程分类 线程按照其调度者可以分为用户级线程和内核级线程两种. 内核级线程 在一个系统上实现线程模型的方式有好几种,因内核和用户空间提供的支持而有一定程度的级别差异.最简单的模 ...

  7. Linux多线程编程---线程间同步(互斥锁、条件变量、信号量和读写锁)

    本篇博文转自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了 ...

  8. c/c++ Linux多线程编程

    Linux多线程编程 线程概念 线程是指运行中的程序的调度单位.一个线程指的是进程中一个单一顺序的控制流,也被称为轻量级线程.它是系统独立调度和分配的基本单位.同一进程中的多个线程将共享该系统中的全部 ...

  9. linux线程 ppt,Linux多线程编程多核编程.ppt

    <Linux多线程编程多核编程.ppt>由会员分享,可在线阅读,更多相关<Linux多线程编程多核编程.ppt(28页珍藏版)>请在装配图网上搜索. 1.Linux多线程编程, ...

最新文章

  1. 在CentOS 6.3 64bit上为Apache Traffic Server 4.2.3挂载SSD并压测
  2. 前端之图形学-2 着色器
  3. [codeigniter]CI中使用pChart绘制图表,已测通过
  4. k8s architecture
  5. 最大公约数 辗转相除法
  6. 作为大龄开发人员,敢问路在何方?
  7. hibernate防止sql注入(转载)
  8. 数学建模应用系列之经济问题
  9. VS2015卸载方式的解决
  10. HybridPose:混合表示下的6D对象姿态估计
  11. RainMeter使用教程一篇
  12. PDF有口令密码怎么移除?
  13. UI基本控件(一):UIScrollView
  14. matlab u 上波浪线,波浪线如何居中,在excel中怎样输入在文字中部加波浪线
  15. 手机无线如何共享给台式计算机,怎么把电脑网络共享给手机上网
  16. 计算机软件 硬件的组成部分,计算机软硬件组成.ppt
  17. html5游戏编程核心技术与实战目录
  18. win10睡眠锁定计算机,Win10专业版电脑睡眠和休眠的区别是什么?
  19. Allegro设置区域规则的方法
  20. 微信小程序实现登录获取头像昵称

热门文章

  1. liunx编译 安装mysql_linux编译安装mysql
  2. f1c100s spi nand 128MB W25N01G 调试记录
  3. Spring DAO(3):Spring 事务管理
  4. 浪潮服务器安装xp系统,浪潮ERP软件安装xp操作系统的电脑无法互相访问的解决方案 | 浪潮888博客...
  5. Java 克隆的优点
  6. 行车记+翻车记:.NET Core 新车改造,C# 节能降耗,docker swarm 重回赛道
  7. 键盘上下左右键返回的键值的问题
  8. FFmpeg开发(八)——Qt视频播放器之多线程的使用(参考了暴风影音、迅雷影音)
  9. 当当网---你怎么了?
  10. 2006年10月4日 星期三