使用omp和mpi并行技术实现蒙特卡罗算法实验 (MonteCarlo)

news2024/12/26 14:21:19

蒙特卡洛算法思想: 画一个正方形和一个内切圆然后在图形上面随机撒点,数一下落在圆

内和正方形内的点的数量之比,就是二者面积之比, 也就是π/4

大数定理告诉我们,随着样本数量的增大,我们用这种方式模拟出来的值应该是越来越趋

近于真实值,样本无穷大的时候收敛于真值。这就证明了蒙特卡罗方法的合理性和有效性。

Mpi基本原理:

  1.什么是MPI

Massage Passing Interface:是消息传递函数库的标准规范,由MPI论坛开发。

一种新的库描述,不是一种语言。共有上百个函数调用接口,提供与C和Fortran语言的绑定

MPI是一种标准或规范的代表,而不是特指某一个对它的具体实现

MPI是一种消息传递编程模型,并成为这种编程模型的代表和事实上的标准

2.MPI的特点

MPI有以下的特点:

消息传递式并行程序设计

指用户必须通过显式地发送和接收消息来实现处理机间的数据交换。

在这种并行编程中,每个并行进程均有自己独立的地址空间,相互之间访问不能直接进行,必须通过显式的消息传递来实现。

这种编程方式是大规模并行处理机(MPP)和机群(Cluster)采用的主要编程方式。

并行计算粒度大,特别适合于大规模可扩展并行算法

用户决定问题分解策略、进程间的数据交换策略,在挖掘潜在并行性方面更主动,并行计算粒度大,特别适合于大规模可扩展并行算法

消息传递是当前并行计算领域的一个非常重要的并行程序设计方式

二、MPI的基本函数

MPI调用借口的总数虽然庞大,但根据实际编写MPI的经验,常用的MPI函数是以下6个:

MPI_Init(…);

MPI_Comm_size(…);

MPI_Comm_rank(…);

MPI_Send(…);

MPI_Recv(…);

MPI_Finalize();

三、MPI的通信机制

MPI是一种基于消息传递的编程模型,不同进程间通过消息交换数据。

1.MPI点对点通信类型

所谓点对点的通信就是一个进程跟另一个进程的通信,而下面的聚合通信就是一个进程和多个进程的通信。

  1. 标准模式:

该模式下MPI有可能先缓冲该消息,也可能直接发送,可理解为直接送信或通过邮局送信。是最常用的发送方式。

由MPI决定是否缓冲消息

没有足够的系统缓冲区时或出于性能的考虑,MPI可能进行直接拷贝:仅当相应的接收完成后,发送语句才能返回。

这里的系统缓冲区是指由MPI系统管理的缓冲区。而非进程管理的缓冲区。

MPI环境定义有三种缓冲区:应用缓冲区、系统缓冲区、用户向系统注册的通信用缓冲区

MPI缓冲消息:发送语句在相应的接收语句完成前返回。

这时后发送的结束或称发送的完成== 消息已从发送方发出,而不是滞留在发送方的系统缓冲区中。

该模式发送操作的成功与否依赖于接收操作,我们称之为非本地的,即发送操作的成功与否跟本地没关系

 

mpi实现MonteCarlo

#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;
}

Mpi:

Mpicxx  ./xxx.cpp -o ./xxx 编译;

Mpirun -n p ./xxx运行;

运行结果:

Mpi:

Omp基本原理:

  OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C、C++和Fortran。OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的并行程序设计。编译器根据程序中添加的pragma指令,自动将程序并行处理,使用OpenMP降低了并行编程的难度和复杂度。当编译器不支持OpenMP时,程序会退化成普通(串行)程序。程序中已有的OpenMP指令不会影响程序的正常编译运行。

  OpenMP执行模式

OpenMP采用fork-join的执行模式。开始的时候只存在一个主线程,当需要进行并行计算的时候,派生出若干个分支线程来执行并行任务。当并行代码执行完成之后,分支线程会合,并把控制流程交给单独的主线程。

一个典型的fork-join执行模型的示意图如下:

OpenMP编程模型以线程为基础,通过编译制导指令制导并行化,有三种编程要素可以实现并行化控制,他们分别是编译制导、API函数集和环境变量。

编译制导

编译制导指令以#pragma omp 开始,后边跟具体的功能指令,格式如:#pragma omp 指令[子句[,子句] …]。常用的功能指令如下:

parallel:用在一个结构块之前,表示这段代码将被多个线程并行执行;

for:用于for循环语句之前,表示将循环计算任务分配到多个线程中并行执行,以实现任务分担,必须由编程人员自己保证每次循环之间无数据相关性;

parallel for:parallel和for指令的结合,也是用在for循环语句之前,表示for循环体的代码将被多个线程并行执行,它同时具有并行域的产生和任务分担两个功能;

sections:用在可被并行执行的代码段之前,用于实现多个结构块语句的任务分担,可并行执行的代码段各自用section指令标出(注意区分sections和section);

parallel sections:parallel和sections两个语句的结合,类似于parallel for;

single:用在并行域内,表示一段只被单个线程执行的代码;

critical:用在一段代码临界区之前,保证每次只有一个OpenMP线程进入;

flush:保证各个OpenMP线程的数据影像的一致性;

barrier:用于并行域内代码的线程同步,线程执行到barrier时要停下等待,直到所有线程都执行到barrier时才继续往下执行;

atomic:用于指定一个数据操作需要原子性地完成;

master:用于指定一段代码由主线程执行;

threadprivate:用于指定一个或多个变量是线程专用,后面会解释线程专有和私有的区别。

相应的OpenMP子句为:

private:指定一个或多个变量在每个线程中都有它自己的私有副本;

firstprivate:指定一个或多个变量在每个线程都有它自己的私有副本,并且私有变量要在进入并行域或任务分担域时,继承主线程中的同名变量的值作为初值;

lastprivate:是用来指定将线程中的一个或多个私有变量的值在并行处理结束后复制到主线程中的同名变量中,负责拷贝的线程是for或sections任务分担中的最后一个线程;

reduction:用来指定一个或多个变量是私有的,并且在并行处理结束后这些变量要执行指定的归约运算,并将结果返回给主线程同名变量;

nowait:指出并发线程可以忽略其他制导指令暗含的路障同步;

num_threads:指定并行域内的线程的数目;

schedule:指定for任务分担中的任务分配调度类型;

shared:指定一个或多个变量为多个线程间的共享变量;

ordered:用来指定for任务分担域内指定代码段需要按照串行循环次序执行;

copyprivate:配合single指令,将指定线程的专有变量广播到并行域内其他线程的同名变量中;

copyin:用来指定一个threadprivate类型的变量需要用主线程同名变量进行初始化;

default:用来指定并行域内的变量的使用方式,缺省是shared。

利用omp_set_num_threads()来设置线程数,

利用#pragma omp parallel sections 声明下面大括号中的语句要并行多线程执行;

利用#pragma omp section 分配线程。

 

omp实现MonteCarlo

#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;
}

 

Omp:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/662017.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玩转电脑|带你了解如何快速查看电脑开关机时间

目录 前言 1、打开管理 2、打开事件查看器 3、打开windows日志 5、获取开机事件 6、获取关机事件 7、保存事件 8、保存事件文件 9、打开事件文件 前言 最近因为一些原因作者想要查看自己电脑每天的的开关机时间记录&#xff0c;但是不知道怎么进行查看&#xff0c;于是在网…

C++重温笔记(十): C++输入输出流

1. 写在前面 c在线编译工具&#xff0c;可快速进行实验: https://www.bejson.com/runcode/cpp920/ 这段时间打算重新把c捡起来&#xff0c; 实习给我的一个体会就是算法工程师是去解决实际问题的&#xff0c;所以呢&#xff0c;不能被算法或者工程局限住&#xff0c;应时刻提…

龙智携手Atlassian亮相DevOps国际峰会:释放团队潜力,以协作挑战不可能

2023年6月29日到30日&#xff0c;龙智将亮相DevOps国际峰会 北京站213展位。本次参展&#xff0c;我们将呈现Atlassian ITSM、DevOps以及工作管理三大解决方案&#xff0c;帮助您释放团队的力量&#xff0c;将不可能变成可能。 立即预约龙智专家面对面交流>>> 龙智自…

BuildAdmin商业级后台管理系统

🚀 CRUD代码生成 图形化拖拽生成后台增删改查代码,自动创建数据表,大气实用的表格、多达22种表单组件支持、拖拽排序、受权限控制的编辑和删除、支持关联表等等,可为您节省大量开发时间。[ 视频介绍 | 使用文档 ] 💥 内置WEB终端 我们内置了WEB终端以实现一些理想中的…

[算法前沿]--019-医学AIGC大模型的构建

基于主动健康的主动性、预防性、精确性、个性化、共建共享、自律性六大特征[1],华南理工大学未来技术学院-广东省数字孪生人重点实验室开源了中文领域生活空间主动健康大模型基座ProactiveHealthGPT,包括:(1) 经过千万规模中文健康对话数据指令微调的生活空间健康大模型扁鹊…

绿色零碳节群硕获奖,为可持续发展提供数字化抓手

6月15日&#xff0c;为探索迈向碳中和之路&#xff0c;第二届国际零碳节暨2023ESG领袖峰会盛大召开。各大绿色品牌与科技集团纷纷现身北京&#xff0c;展示低碳生产与绿色发展的科技成果。群硕也携带创新数字化产品与解决方案亮相国际绿色零碳节&#xff0c;并荣获2023绿色可持…

文献阅读:智能网联环境下面向语义通信的资源分配

目录 智能网联环境下面向语义通信的网络架构模型驱动和数据驱动资源分配算法对比计算卸载和协同计算未来研究方向参考文献 智能网联环境下面向语义通信的网络架构 车辆借助车联网将基于语义理解的计算任务进一步卸载到计算资源丰富的移动边缘计算服务器&#xff08;通常部署在路…

忆联主导消费级存储权威标准制定,推动行业规范化发展

近日&#xff0c;由记忆科技旗下公司忆联主导的团体标准《消费级固态硬盘可靠性及环境适应性规范》&#xff08;以下简称&#xff1a;规范&#xff09;研讨会顺利召开。此次会议完善了《规范》中的相关内容与细节&#xff0c;以确保消费级固态硬盘在可靠性方面能更进一步地满足…

沙利文头豹研究院发布《2023年腾讯云数据安全能力中心分析报告》

2023年6月15日&#xff0c;分析机构沙利文&#xff08;Frost & Sullivan&#xff09;头豹研究院发布《2023年腾讯安全数据安全能力中心分析报告》&#xff08;下文简称&#xff1a;报告&#xff09;&#xff0c;报告针对腾讯安全在数据安全领域的解决思路、产品、安全体系、…

在微信公众平台注册一个小程序开发账号

我们先访问地址 https://mp.weixin.qq.com/ 进入微信公众平台 如果您是第一个进入 直接点上面的 立即注册即可 然后 他会让我选择账号类型 我们要做的是小程序开发 所以 一定要选择小程序的账号类型 下一个界面并没有价值 直接点前往注册即可 注册主要分三个节点 第一步 填…

网络安全学术顶会——CCS '22 议题清单、摘要与总结(中)

注意&#xff1a;本文由GPT4与Claude联合生成。 81、HammerScope: Observing DRAM Power Consumption Using Rowhammer 内存单元尺寸的不断缩小使得内存密度提高&#xff0c;功耗降低&#xff0c;但同时也影响了其可靠性。Rowhammer攻击利用这种降低的可靠性在内存中引发比特翻…

从零使用source insight并完成必要设置

文章目录 1 创建新工程2 打开四大窗口3 更改编码方式5 修改背景颜色为护眼色6 设置批量注释和批量取消注释7 选择变量高亮其他相同变量也高亮8 自定义快捷键 1 创建新工程 点new project&#xff0c;改成自己熟悉的名字 选择源文件路径 add tree 加载完成后点close 然后点Pr…

【vue导入导出Excel】vue简单实现导出和导入复杂表头excel表格功能【纯前端版本和配合后端版本】

前言 这是一个常用的功能&#xff0c;就是导入和导出excel表格 但是时常会遇到一些复杂表头的表格导出和导入 比如我这个案例里面的三层表头的表格。 网上看了下发现了一个非常简单导出和导入方法 当然这个是纯前端的版本&#xff0c;会出现分页不好下载的情况。所以实际工作中…

深入分析Go语言与C#的异同

摘要&#xff1a;本文由葡萄城技术团队于CSDN原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 为了更加深入地介绍Go语言以及与C#语言的比较&#xff0c;本文将会从多个维度出发…

ppt怎么录制视频和声音 ppt怎么录制人像

ppt在课堂上是非常重要的工具&#xff0c;许多微课都是通过ppt讲授。ppt的功能日新月异&#xff0c;之前的ppt仅具有演示功能&#xff0c;如今pp录制视频t还是可以的。ppt怎么录制视频和声音&#xff1f;首先&#xff0c;我们得创建一个ppt&#xff0c;然后再进行录制。ppt怎么…

【Python 随练】分解质因数

题目&#xff1a; 将一个正整数分解质因数。例如&#xff1a;输入 90,打印出90233*5。 简介&#xff1a; 在本篇博客中&#xff0c;我们将解决一个数学问题&#xff1a;如何将一个正整数分解成质因数的乘积。我们将给出问题的解析&#xff0c;并提供一个完整的代码示例来实现…

【Python】解决pandas读取excel,以0向前填充的数字会变成纯数字

1 问题 test.xlsx的内容如下 序号code000012310001242000125 df pd.read_excel(test.xlsx)读取后的codel列&#xff0c;样例如下 序号code012311242125 显然这不是我想要的结果。 2 解决办法 &#xff08;1&#xff09;第一种 指定列以字符串读取 df pd.read_excel(t…

在 ZBrush、Blender 和 Substance 3D Painter 中重新创建 Bowser

今天瑞云渲染小编给大家带来一篇mral Ismayilov作者Bowser 项目背后的工作流程&#xff0c;展示了头发是如何修饰的&#xff0c;并解释了纹理化过程。 简介 大家好&#xff0c;我是尤姆拉尔-伊斯马伊洛夫&#xff0c;是一名3D角色艺术家和动作设计师&#xff0c;在阿塞拜疆的巴…

【CMake 入门与进阶(10)】 CMake如何定义函数,内部参数及作用域(附代码)

前几篇已经学习了cmake 中常用的命令 command、变量 variable &#xff0c;相信大家已经掌握了 cmake 工具的基本使用方法&#xff1b;本文我们进一步学习 cmake&#xff0c;看看 cmake 还有哪些东西。 定义函数 在 cmake 中我们也可以定义函数&#xff0c;cmake 提供了 funct…

基于图神经网络的切片级漏洞检测及解释方法

源自&#xff1a;软件学报 作者&#xff1a;胡雨涛 王溯远 吴月明 邹德清 李文科 金海 摘 要 随着软件的复杂程度越来越高, 对漏洞检测的研究需求也日益增大. 软件漏洞的迅速发现和修补, 可以将漏洞带来的损失降到最低. 基于深度学习的漏洞检测方法作为目前新兴的检测手…