用蒙特卡罗方法求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值计算方法收敛速度较慢,但是非常优美,随机数的威力是很强大的。这类算法具有很好的并行化能力,各节点几乎不需要作信息交换,独立完成自己的计算工作。

posted @ 2024-04-30 22:23  棒打鲜橙不加冰  阅读(15)  评论(0编辑  收藏  举报