我的并行计算之路(二)MPI点对点通信MPI_Send和MPI_Recv
学习了MPI的点对点技术后,来博客记录一下。先上完整地代码:
#include<bits/stdc++.h>
#include<mpi.h>using namespace std;
int comm_sz=0;
int my_rank=0;
int arra[]={1,2,3,4,5},arrb[]={10,9,8,7,6},arrc[]={0,0,0,0,0};//获取输入,0进程从键盘读取,非0进程从0进程获取
bool get_input(double &a,double &b,int n)
{if(my_rank==0){ //用户输入cout<<" enter a,b,n"<<endl;cin>>a>>b>>n;}else{ //从进程0获取MPI_Recv(&a,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);MPI_Recv(&b,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);MPI_Recv(&n,1,MPI_INT,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);}return true;
}//加和数组a和数组b的对应项
int count_sum(int beg,int en)
{int sum=0;for(int i=beg;i<en;i++){sum += arra[i]+arrb[i];}return sum;
}int main(void)
{int local_sum=0,total_sum=0; //local_sum为本进程使用,total_sum为计算风格进程的合使用MPI_Init(NULL,NULL);MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);MPI_Comm_size(MPI_COMM_WORLD,&comm_sz);//get_input(a,b,n); //测试时用的int n = sizeof(arra)/sizeof(int);int jiange=n/(comm_sz-1);if(my_rank==0){ //进程0收集各个进程的结果,然后加和cout<<"n: "<<n<<endl;for(int source=1;source<comm_sz;source++){MPI_Recv(&local_sum,1,MPI_INT,source,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);total_sum += local_sum;}cout<<"total_sum: "<<total_sum<<endl;}else if(my_rank==(comm_sz-1)){ //最后一个进程用来处理剩下的数据int rest=n-jiange*(comm_sz-2);int sum=count_sum(n-rest,n);MPI_Send(&sum,1,MPI_INT,0,0,MPI_COMM_WORLD);}else{ //非0,非最后进程来计算jiange内的数据和int sum=count_sum(jiange*(my_rank-1),jiange*my_rank);MPI_Send(&sum,1,MPI_INT,0,0,MPI_COMM_WORLD);}MPI_Finalize();return 0;
}
首先是几个函数接口:
MPI系统初始化函数MPI_Init( )。原型如下:
int MPI_Init(int * argc_p, /* IN */char*** argv_p /* OUT */);
参数**argc_p,*argv_p是指向argc,argv的指针,可以只设置成NULL*。返回值为错误码。初始化函数对系统进行了必要的初始化设置,例如,系统可能要为消息缓冲区分配存储空间,为进程指定进程号等。在程序调用MPI_Init( )前,不应该调用其他的MPI函数。
MPI使用完毕后,调用MPI_Finalize( )函数,将分配的资源释放,函数原型:
int MPI_Finalize(void);
在调用MPI_Finalize( )函数后,就不要再调用MPI的函数了。下面介绍MPI_Comm_size()函数和MPI_Comm_size()函数。函数原型为:
int MPI_Comm_size(MPI_Comm comm, /* IN */int* com_sz_p /* OUT */);int MPI_Comm_rank(MPI_Comm comm,int* my_rank_p)
MPI_Comm_size()函数用来得到创建的进程数量,MPI_Comm_rank()函数用来得到当前进程编号。接下来就是点对点通信的重点MPI_Send()和MPI_Recv()函数。函数原型:
int MPI_Send(void* msg_buf_p, /* IN */int msg_size, /* IN */MPI_Datatype msg_type, /* IN */int dest, /* IN */int tag, /* IN */MPI_Comm communicator /* IN */);
MPI_Send()函数中msg_buf_p、msg_size 和 msg_type定义了消息的内容,dest、tag 和 communicator定义了消息的目的地。
int MPI_Recv(void* msg_buf_p, /* OUT */int buf_size, /* IN */MPI_Datatype buf_type, /* IN */int source, /* IN */int tag, /* IN */MPI_Comm communicator, /* IN */MPI_Status* status_p /* OUT */);
MPI_Recv()函数中,msg_buf_p指向内存块,buf_size指定了内存中要存储对象的数量,buf_type说明了对象的类型。后面的三个参数用来识别参数,source用来指定接收从哪个进程发来的消息,tag需要与发送消息的参数tag相匹配,communicator需要与发送进程的通信子匹配。status_p一般不使用这个参数,赋予特殊的常量MPI_STATUS_IGNORE就好。
用qqq号进程调用
MPI_Send(send_buf_p,send_buf_sz,send_type,dest,send_tag,send_comm)
发送的消息能被rrr号进程调用
MPI_Recv(recv_buf_p,recv_buf_sz,recv_type,src,recv_tag,recv_comm)
函数接收到,需要满足:
- send_comm==recv_comm
- send_tag==recv_tag
- dest==r && c==q
若要成功接收,还需要保证recv_buf_sz⩾\geqslant⩾send_buf_sz
接下来,讲一下程序的思路。每个进程被创建后,获取自己的进程号my_rank和进程总数comm_sz,然后计算非0进程需要计算的平均个数jiange。
非0号进程根据jiange和my_rank找到自己计算的区间,然后计算每一位对应的数组a和数组b的和,最后将结果用MPI_Send()函数发送给0号进程。
0号进程通过MPI_Recv()函数接收其他各个进程的结果,将各个结果加起来,计算一个总和。
其中,比较特殊的是最后一个非0进程,因为会存在计算量不能被进程平均分的情况,例如5个计算量,被2个非0进程分配。所以,最后一个进程就用来将剩下没有被分配到的计算量给计算了。
参考文献
[1] (美)Pacheco.An Introduction to Parallel Programming[M].邓倩妮等译.北京:机械工业出版社,2012.8
我的并行计算之路(二)MPI点对点通信MPI_Send和MPI_Recv相关推荐
- 我的并行计算之路(三)MPI集合通信之Scatter和Gather
集合通信对比点对点通信来说,确实要方便许多,基本上不需要考虑各个进程该怎么发送,该怎么接收的问题,只要是使用一个通信子,函数接口自己就完成了.从进程的角度考虑,集合通信在分配任务量的时候更加平均,使各 ...
- App项目实战之路(二):API篇
原创文章,转载请注明:转载自Keegan小钢 并标明原文链接:http://keeganlee.me/post/practice/20160812 微信订阅号:keeganlee_me 写于2016- ...
- 六级考研单词之路-二十一
title: 六级考研单词之路-二十一 date: 2020-12-08 11:31:40 tags: 六级考研单词之路 Day21 1.steak[n.牛排,肉排] 2.rice[n.米饭] 3.s ...
- ES进阶之路二(ES7-ES12)
简介 JavaScript是世界上发展最快的编程语言之一,不仅可以用于编写运行在浏览器的客户端程序,随着Node.js的发展,JavaScript也被广泛应用于编写服务端程序.而随着JavaScrip ...
- ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14(ES进阶之路二)
简介 JavaScript是世界上发展最快的编程语言之一,不仅可以用于编写运行在浏览器的客户端程序,随着Node.js的发展,JavaScript也被广泛应用于编写服务端程序.而随着JavaScrip ...
- 六级考研单词之路-二十
title: 六级考研单词之路-二十 date: 2020-12-07 12:07:45 tags: 六级考研单词之路 Day20 1.chemistry[n.化学] eg: She chose to ...
- 六级考研单词之路-二十八
title: 六级考研单词之路-二十八 date: 2020-12-17 12:29:40 tags: 六级考研单词之路 Day28 1.up[adv.向上] eg: Put the packet u ...
- 六级考研单词之路-二十六
title: 六级考研单词之路-二十六 date: 2020-12-15 16:43:28 tags: 六级考研单词之路 Day26 1.big[adj.大的] 2.bloody[n.流血的,血腥的] ...
- 前端Vue学习之路(二)-Vue-router路由
Vue学习之路 (二) Vue-router(基础版) 一.增加静态路由 二.动态路由+路由嵌套+404页面 三. 编程式导航 四.命名路由 五.命名视图 六.重定向和起别名 1.重定向 2.起别名 ...
- 老兵的十年职场之路(二)
在上一篇文章老兵的十年职场之路(一) 里头,讲述了我在初入职场时的一些经历,从自己个人的感受来说并不是特别的美好,既没有职位上的屌丝逆袭.也没有令人兴奋的意外成长,但也许这也是很多人所经历过的,毕竟我 ...
最新文章
- PonyAI的首份美国无人出租成绩单:总数1271趟,15%拼车
- C#类中操作UI层控件状态[原]
- js基础-字符串常用属性合集
- 互动整合营销_营销成本日益升高,整合营销到底有多重要
- Java数据类型和MySql数据类型对应表
- TCP中的RTT和RTO
- 精通PHP的十大要点
- Redis未授权访问缺陷让服务器沦为肉鸡
- 适合用做公司官网WordPress主题风格免受权版本
- Ubuntu实用安装
- 笔记本电脑禁用集显会变卡?
- Bilibili综合分析
- 关于多个ul标签并列时下对齐的问题
- 哎哟,不错哦之玩乐动物园
- 计算机里面不显示光驱位硬盘,Windows10系统识别不了光驱位机械硬盘怎么办?解决方法...
- win 10计算机文件,Win10电脑怎么转移c盘文件?
- JMeter - REST API测试 - 完整的数据驱动方法(翻译)
- Windows程序入口
- iOS开发之语音朗读文字
- android中textview记录日志,Android中TextView属性全纪录