用蒙特卡罗方法求p
实验任务:
基于蒙特卡罗思想用MPI程序实现对p值的并行求解
实验目的:
掌握蒙特卡罗算法并行化的实现方法
实现方法:
根据蒙特卡罗方法的思想,我们以坐标原点为圆心作一个直径为1的单位圆,再作一个正方形与圆相切,在这个正方形内随机产生count点,判断是否落在圆内,将落在圆内的点数目计作m,根据概率理论,m与count的比值近似可以看成圆和正方形的面积之比,由于圆的半径为0.5,正方形的边长为1,我们有m/count=p0.5^2/1,则p值可以用以上公式计算:p=4m/count。本实验就采用这一方法来计算p的近似值。
代码示例:
#include"mpi.h" #include<stdio.h> #include<stdlib.h> int main(int argc,char **argv) { int myid,numprocs; int namelen,source; long count=1000000; char processor_name[MPI_MAX_PROCESSOR_NAME]; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&myid); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Get_processor_name(processor_name,&namelen); srand((int)time(0)); double y; double x; long m=0,m1=0,i=0,p=0; double pi=0.0,n=0.0; for(i=0;i<count;i++) { x=(double)rand()/(double)RAND_MAX; y=(double)rand()/(double)RAND_MAX; if((x-0.5)*(x-0.5)+(y-0.5)*(y-0.5)<0.25) m++; } n=4.0*m/1000000; printf("Process %d of %d on %s pi= %f\n",myid,numprocs,processor_name,n); if(myid!=0) { MPI_Send(&m,1,MPI_DOUBLE,0,1,MPI_COMM_WORLD); } else { p=m; for(source=1;source<numprocs;source++) { MPI_Recv(&m1,1,MPI_DOUBLE,source,1,MPI_COMM_WORLD,&status); p+=m1; } printf("pi=%f\n",4.0*p/(count*numprocs)); } MPI_Finalize(); }
运行结果:
程序说明:
本例在设计时引入numprocs参数,即总的节点数,通过对参数的使用可以实现在机群节点个数发生变化时不用 对程序作任何修改,我们通常再编写并行程序时都要求能对节点的数目进行动态适应,也就是节点可扩展。在示例中各节点对落入圆内的随机点进行计数,并将计算结果发送到主节点,由主节点对所有数据汇总,并计算p值。系统打印出各节点计算的p值和汇总后的p值。这种p值计算方法收敛速度较慢,但是非常优美,随机数的威力是很强大的。这类算法具有很好的并行化能力,各节点几乎不需要作信息交换,独立完成自己的计算工作。