【MPI OpenMP】并行蒙特卡洛方法求圆周率(C语言)

本文记录了使用MPI与OpenMP两种并行计算方法实现蒙特卡洛计算圆周率,题目是专业实验课上老师给的,主要分享一下自己的做法,希望大家不吝赐教(使用的语言是C语言)。

蒙特卡洛方法求圆周率

  • 蒙特卡洛方法的原理
    该方法的原理还是比较简单的,网上资料也有很多,我的实验课老师也提供了一个参考资料,如果大家想看看蒙特卡洛计算圆周率的原理,可以自行查看一下:蒙特卡洛方法求圆周率与定积分及python实现。这位博主分享的写法是python的,并且除了计算了圆周率,还计算了定积分,但我只是查看了其中的原理部分。
  • 为什么要使用并行算法
    因为蒙特卡洛求圆周率就是模拟向正方形区域撒点嘛,计算落在圆中的点数,撒的点越多,计算出来的圆周率越精确,但是此时会存在一个问题,那就是点太多了之后,算法的运行时间会很长;而恰好模拟撒点这件事是可以并行实现的,也就是说,撒的点之间不影响,所以可以让多个进程或者线程同时进行撒点,最后将所有进/线程撒的点一起统计,得到精度更高的圆周率。
  • 我使用的方法
    计算圆周率的撒点有很多方式,我是用的是使用单位圆在第一象限的部分进行模拟(如下图),第一象限中正方形的面积为1,四分之一圆的面积为pi/4,因此可以根据四分之一圆与正方形中的点数比来估计圆周率,如正方形中点数为N,四分之一圆内点数为n,则圆周率 pi = 4*N/n。
    单位圆

MPI方法

MPI方法是通过多线程方式实现的并行计算,方式很多,本人使用的是两个虚拟机,使用前需要配置两个虚拟机,并需要写相关配置文件,但是本文主要是分享蒙特卡洛方法,就不讲解如何配置虚拟机了。

  • 思路
    模拟撒点的总点数是通过参数获取;进而可以判断总点数是否能整除总进程数, 将能够整除的点数部分均分给每个进程,剩余的不能均分的部分由根进程进行模拟;最后将每个进程模拟的结果统计,输出所估计的圆周率,并输出并行算法的时间。
  • 代码
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<mpi.h>

long long int get_num(long long int n)
{
    double x,y,d;   //模拟生成的点(x,y),以及该点到原点的距离d
    long long int num = 0, i;   //落入四分之一圆的点数
    srand(time(NULL));   //随机种子
    for(i=0; i<n; i++){
        x=(double)rand()/(double)RAND_MAX;
        y=(double)rand()/(double)RAND_MAX;
        d=x*x+y*y;
        if(d<=1)
            num += 1;
    }
    return num;
}

int main(int argc,char** argv){
    long long int n;
    int size,rank;
    MPI_Comm comm = MPI_COMM_WORLD;
    MPI_Status status;
    MPI_Init(&argc,&argv); //初始化
    MPI_Comm_size(comm,&size);  //进程总数
    MPI_Comm_rank(comm,&rank);  //当前进程标识
    sscanf(argv[1],"%lld",&n);  //通过参数获取一共模拟多少个点

    clock_t startTime, endTime;   //并行时间
    startTime=clock();
    MPI_Bcast(&n,1,MPI_LONG_LONG,0,comm);   //将总数广播到每个进程
    
    long long int Num, num;   //所有进程的落入四分之一圆区域的总点数与每个进程的落入四分之一圆区域的总点数
    num = get_num(n/size);  //计算每个进程能均分的点数
    MPI_Barrier(comm);
    MPI_Reduce(&num,&Num,1,MPI_LONG_LONG,MPI_SUM,0,comm);   //将每个进程计算的结果求和
    if(rank==0){
        if(num%size != 0)   //根进程计算不能整除的点数
            Num += get_num(n%size);
        double pi=(double)Num/(double)n*4;   //根据开头分析的公式计算圆周率
        endTime=clock();
        printf("pi=%lf\n",pi);
        printf("并行计算时间time=%dms\n",int(endTime-startTime));  //输出并行时间
    }
    
    MPI_Finalize();
    return 0;
}
  • 结果
    分别使用1、2、4个进程模拟8000000与10000000个点,结果如下
    结果

OpenMP

  • 思路
    OpenMP的思路就十分简单粗暴了,使用多线程的思想,由于多线程是共享内存,所以无脑地将串行代码中的for循环修改成OpenMP并行代码即可,但是此处需要注意一个问题,由于多线程共享内存,直接将num设置为共享变量,容易导致多个线程共同使num加1的时候丢失数据(比如num为1,某个线程让num变成2,但是还没写进内存,另一个线程也将num读取,给num加1,并写入内存,所以此时会将前一个线程的操作丢失),不过,openmp提供了一个解决方案,在进行并行时,使用reduction声明num,即将每个线程都会对num进行拷贝,在所有线程计算结束后,将所有线程的num加起来
  • 代码
#include <omp.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>

int main(int argc,char** argv){
    long long int n, num = 0, i;
    double x,y,d;
    int num_thread = atoi(argv[2]);
    
    sscanf(argv[1],"%lld",&n);
    
    clock_t startTime, endTime;
    startTime=clock();
    
    srand(time(NULL));
    omp_set_num_threads(num_thread);
    #pragma omp parallel shared(n) private(i,x,y,d) reduction(+:num)
    {
        #pragma omp for schedule(guided)
        for(i=0; i<n; i++) {     
            x=(double)rand()/(double)RAND_MAX;
            y=(double)rand()/(double)RAND_MAX;
            d=x*x+y*y;
            if(d<=1)
                num += 1;
        }
    }
    double pi=(double)num/(double)n*4;
    endTime=clock();
    printf("pi=%lf\n",pi);
    printf("并行计算时间time=%dms\n",int(endTime-startTime));
    
    return 0;
}
  • 结果
    结果
  • 8
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: MPIOpenMP是两种常见的并行程序设计模型,用于实现并行计算。 MPI,全称为Message Passing Interface,是一种消息传递接口,适用于分布式内存系统下的并行计算。MPI程序由多个进程组成,每个进程拥有自己的独立内存空间,它们通过消息传递来进行通信和同步。MPI程序可以在不同的计算节点上运行,通过网络传输消息。 OpenMP是一种共享内存的并行编程模型,适用于多核系统和共享内存架构。OpenMP程序使用线程来并行执行任务,线程之间可以访问共享内存。OpenMP程序在单个计算节点上运行,并利用线程的方式实现任务的并行执行。 C语言是一种高级编程语言,非常适合并行程序设计。C语言提供了丰富的并行编程库和函数,例如MPIOpenMPMPIOpenMP可以与C语言结合使用,实现并行计算。 在MPIOpenMP并行程序设计的C语言版PDF中,我们可以学习如何使用C语言编写MPIOpenMP程序。该PDF将详细介绍MPIOpenMP的概念、语法和函数,以及如何在C语言中实现并行计算。通过学习该PDF,我们可以掌握使用C语言编写高效的并行程序的技巧和方法。 总之,MPIOpenMP是两种常见的并行程序设计模型,适用于不同类型的并行计算环境。在C语言版的MPIOpenMP并行程序设计PDF中,我们可以学习如何使用C语言编写MPIOpenMP程序,从而实现高效的并行计算。 ### 回答2: 《MPIOpenMP并行程序设计:C语言版》是一本以C语言为基础,介绍MPIOpenMP并行程序设计的教材。MPI(Message Passing Interface)是一种消息传递接口,用于实现并行计算中不同节点之间的数据传递和通信。而OpenMP是一种共享内存并行编程模型,通过在代码中插入指令来实现并行化。 这本教材首先介绍了MPIOpenMP的基本概念和工作原理。它详细讲解了MPI的通信操作和数据类型,在编写并行程序时如何使用MPI函数进行进程之间的通信。同时也介绍了OpenMP的指令和语法,以及如何在C语言程序中使用OpenMP进行多线程并行计算。 教材还特别强调了MPIOpenMP的结合使用。它介绍了如何在一个程序中同时使用MPIOpenMP,使得程序既能进行跨节点的并行计算,又能在每个节点的多个处理器中进行并行计算。这种结合使用可以充分发挥集群计算机的计算能力,提高程序的运行效率。 此外,教材还提供了大量的例子和实践操作,帮助读者理解并掌握MPIOpenMP并行程序设计。通过实践操作,读者可以学会如何在C语言中使用MPIOpenMP编写并行程序,体会到并行计算的优势和挑战。 总的来说,《MPIOpenMP并行程序设计:C语言版》是一本很好的教材,适合想要学习并行程序设计的C语言程序员。它全面介绍了MPIOpenMP的概念和应用,通过实例和实践操作帮助读者掌握并行计算的基本原理和实现方法。无论是对于学术研究还是实际应用,这本书都是一本很有价值的参考书籍。 ### 回答3: MPI(Message Passing Interface)和OpenMP(Open Multi-Processing)是用于并行程序设计的两种常见的标准。MPI适用于分布式内存计算机集群,而OpenMP适用于共享内存计算机架构。 MPI提供了一套函数接口,允许程序员在多个计算节点上进行并行计算。它允许进程之间通过消息传递来交换数据和同步计算。在MPI中,可以通过创建不同的进程,并通过消息传递进行通信来实现并行计算。这使得程序能够在不同的计算节点上同时运行,从而提高了整体的计算性能。 OpenMP是一套用于共享内存并行编程的指令集,允许程序员通过在代码中添加特定的指令来实现并行计算。OpenMP采用线程并行的方式,允许多个线程同时执行程序的不同部分。在OpenMP编程中,可以通过添加预处理指令来定义并行区域,从而使多个线程同时执行其中的任务。这种方式可以有效地利用计算机的多核处理器,提高程序的执行效率。 MPIOpenMP在不同的计算环境中起作用。如果要在多个计算节点上进行并行计算,使用MPI会更合适。MPI可以在集群中的多个计算节点之间进行通信,允许分布式计算。如果计算机具有多个核心并且共享内存,那么使用OpenMP可能更合适。OpenMP可以利用计算机的多核处理器来实现并行计算。 总结而言,MPIOpenMP是用于并行程序设计的常见工具。选择使用哪种工具取决于计算机的架构和需要解决的问题。MPI适用于分布式内存计算机集群,而OpenMP适用于共享内存计算机架构。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谛凌

本人水平有限,感谢您支持与指正

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值