学习了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_sizemsg_type定义了消息的内容,dest、tagcommunicator定义了消息的目的地。

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相关推荐

  1. 我的并行计算之路(三)MPI集合通信之Scatter和Gather

    集合通信对比点对点通信来说,确实要方便许多,基本上不需要考虑各个进程该怎么发送,该怎么接收的问题,只要是使用一个通信子,函数接口自己就完成了.从进程的角度考虑,集合通信在分配任务量的时候更加平均,使各 ...

  2. App项目实战之路(二):API篇

    原创文章,转载请注明:转载自Keegan小钢 并标明原文链接:http://keeganlee.me/post/practice/20160812 微信订阅号:keeganlee_me 写于2016- ...

  3. 六级考研单词之路-二十一

    title: 六级考研单词之路-二十一 date: 2020-12-08 11:31:40 tags: 六级考研单词之路 Day21 1.steak[n.牛排,肉排] 2.rice[n.米饭] 3.s ...

  4. ES进阶之路二(ES7-ES12)

    简介 JavaScript是世界上发展最快的编程语言之一,不仅可以用于编写运行在浏览器的客户端程序,随着Node.js的发展,JavaScript也被广泛应用于编写服务端程序.而随着JavaScrip ...

  5. ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14(ES进阶之路二)

    简介 JavaScript是世界上发展最快的编程语言之一,不仅可以用于编写运行在浏览器的客户端程序,随着Node.js的发展,JavaScript也被广泛应用于编写服务端程序.而随着JavaScrip ...

  6. 六级考研单词之路-二十

    title: 六级考研单词之路-二十 date: 2020-12-07 12:07:45 tags: 六级考研单词之路 Day20 1.chemistry[n.化学] eg: She chose to ...

  7. 六级考研单词之路-二十八

    title: 六级考研单词之路-二十八 date: 2020-12-17 12:29:40 tags: 六级考研单词之路 Day28 1.up[adv.向上] eg: Put the packet u ...

  8. 六级考研单词之路-二十六

    title: 六级考研单词之路-二十六 date: 2020-12-15 16:43:28 tags: 六级考研单词之路 Day26 1.big[adj.大的] 2.bloody[n.流血的,血腥的] ...

  9. 前端Vue学习之路(二)-Vue-router路由

    Vue学习之路 (二) Vue-router(基础版) 一.增加静态路由 二.动态路由+路由嵌套+404页面 三. 编程式导航 四.命名路由 五.命名视图 六.重定向和起别名 1.重定向 2.起别名 ...

  10. 老兵的十年职场之路(二)

    在上一篇文章老兵的十年职场之路(一) 里头,讲述了我在初入职场时的一些经历,从自己个人的感受来说并不是特别的美好,既没有职位上的屌丝逆袭.也没有令人兴奋的意外成长,但也许这也是很多人所经历过的,毕竟我 ...

最新文章

  1. PonyAI的首份美国无人出租成绩单:总数1271趟,15%拼车
  2. C#类中操作UI层控件状态[原]
  3. js基础-字符串常用属性合集
  4. 互动整合营销_营销成本日益升高,整合营销到底有多重要
  5. Java数据类型和MySql数据类型对应表
  6. TCP中的RTT和RTO
  7. 精通PHP的十大要点
  8. Redis未授权访问缺陷让服务器沦为肉鸡
  9. 适合用做公司官网WordPress主题风格免受权版本
  10. Ubuntu实用安装
  11. 笔记本电脑禁用集显会变卡?
  12. Bilibili综合分析
  13. 关于多个ul标签并列时下对齐的问题
  14. 哎哟,不错哦之玩乐动物园
  15. 计算机里面不显示光驱位硬盘,Windows10系统识别不了光驱位机械硬盘怎么办?解决方法...
  16. win 10计算机文件,Win10电脑怎么转移c盘文件?
  17. JMeter - REST API测试 - 完整的数据驱动方法(翻译)
  18. Windows程序入口
  19. iOS开发之语音朗读文字
  20. android中textview记录日志,Android中TextView属性全纪录

热门文章

  1. CPU卡FM1208发卡操作流程(不带密钥验证)
  2. 1.1Vue安装以及使用(node安装)
  3. 视频压缩 I P B 帧 详解
  4. r 语言计算欧氏距离_R语言实现46种距离算法
  5. 统计思维(实例5)——变量之间的关系
  6. 在vue中使用unity3D实现webGL将要呈现的效果
  7. 【JAVA】金额工具类 金额千分位、中文大写金额、英文金额
  8. 两路VL53L0X激光测距传感器的使用
  9. ios第3天的气泡作业
  10. 基于 STM32F412RE 的 Flappy bird 游戏机实现