《并行程序设计导论》第三章:
三、MPI实现
3.点对点通信
(1)发送: MPI_Send函数:
函数原型:
int MPI_Send(
void* msg_buf_p,
int msg_size,
MPI_Datatype msg_type,
int dest,
int tag,
MPI_Comm communicator){...}
参数解释:
①void* msg_buf_p:
消息的地址。
②int msg_size:
消息的大小(字节数)。
③MPI_Datatyoe msg_type:
MPI自己的数据类型。
④int dest:
发送消息的目的地,也就是接收进程的进程号。
⑤int tag:
标签,用于区分多个消息。随意设置(如0、1、2…),但MPI_Send与MPI_Recv的tag值相等接收成功。
⑥MPI_Comm communicator:
通信子名字。
⑦返回值:
错误码。
函数作用:
当前调用此函数的进程,将msg_buf_p指向的内存中msg_size大小的msg_type类型的消息,并打上tag标签后,发给名叫communicator通信子中序号为dest的进程。
(2)接收: MPI_Recv函数:
函数原型:
int MPI_Recv(
void* msg_buf_p,
int buf_size,
MPI_Datatype buf_type,
int source,
int tag,
MPI_Comm communicator,
MPI_Status* status_p){...}
参数解释:
①void* msg_buf_p:
接收到的消息要存放的地址。
②int buf_size:
消息存放区的大小(字节数)。
③MPI_Datatype buf_type:
消息存放区的数据类型。
④int source:
接收消息的来源地,也就是发送这个消息的进程的进程号。注意,只有在MPI_Recv函数中才存在一个特殊的MPI常量:MPI_ANY_SOURCE意为可以接收任意来源进程的信息。
⑤int tag:
标签,用于区分多个消息。随意设置(如0、1、2…),但MPI_Send与MPI_Recv的tag值相等接收成功。注意,只有在MPI_Recv函数中才存在一个特殊的MPI常量:MPI_ANY_TAG意为可以接收任意标签值的信息。
⑥MPI_Comm communicator:
通信子名字。
⑦MPI_Status* status_p
大部分情况下,我们并不使用这个参数,通常用特殊的MPI常量MPI_STATUS_IGNORE填写参数。更深一步:该参数实际上存放有来源地相关的信息,可以用MPI_Get_count函数来得到。
⑧返回值:
错误码。
函数作用:
当前调用此函数的进程接收来自名为communicator通信子中进程号为source的进程发来的消息,并将此消息存放在msg_buf_P指向的buf_type类型且大小为buf_size的内存区域中。
(3)MPI_Datatype类型

(4)send与recv的作用机理
①MPI_Recv是阻塞型(挂起型),必须要有与之配对的MPI_Send函数在MPI缓存中,MPI_Recv才会激活工作。
②更进一步:同一组收发配对进程调用MPI_Send函数与MPI_recv有严格的顺序关系,如:进程1先Send一个A消息到进程2,再Send一个B消息到进程2,那么进程2一定是先接收A再接收B,无论进程2的MPI_Recv的顺序如何。
③更进一步:MPI_Send函数,是将消息传递到MPI缓存中便返回,而MPI_Recv函数是进程成功接收到消息后才返回。
(5)练习
请将下面的代码补充完整
/*介绍:
*由0号进程输出:进程0中的a的值与进程1中的a的值与进程2中的a的值的和
*/
/*----头文件------*/
#include <stdio.h>
#include <?>//请补充:MPI头文件
/*---------------*/
/*---建立全局变量---*/
MPI_? comm;//请补充:通信子的MPI类型
int comm_sz;
int my_rank;
/*-------------------*/
int main(int argc,int* argv[]){
MPI_//请补充:MPI初始化
comm = ?;//请补充:通信子名
MPI_//请补充:获得通信子大小返回给comm_sz
MPI_//请补充:获得当前进程号返回给my_rank
int a = 5;
int b = 0;
int c = 0;
int sum = 0;
if(my_rank==1){
a = 7;
MPI_Send(&a,1,MPI_INT,0,0,comm);
}
if(my_rank==2){
a = 9;
MPI_Send();//请补充:将a的值发送给0号进程,tag值为1
}
if(my_rank==0){
MPI_Recv();//请补充:接收来自1号进程的消息并存入b中
MPI_Recv(&c,1,MPI_INT,2,1,comm,MPI_STATUS_IGNORE);
sum = a+b+c;
printf("I am proc%d in %d,proc0a+proc1a+proc2a=%d\n",my_rank,comm_sz,sum);
}
MPI_Finalize();
}
本文深入探讨了MPI(Message Passing Interface)中的点对点通信机制,详细解析了MPI_Send和MPI_Recv函数的参数与作用机理。通过具体代码示例,展示了如何在并行环境中实现进程间的数据交换。
2306

被折叠的 条评论
为什么被折叠?



