目录
一、组收集
二、全互换
三、同步
四、规约
五、预定义的归约操作
上一节内容我们介绍了MPI组通信的基本概念和广播、收集、散发接口调用。本节我们继续介绍其余的组通信接口。
一、组收集
MPI_GATHER是将数据收集到ROOT进程,MPI_ALLGATHER相当于每一个进程都作为ROOT执行一次MPI_GATHER调用,即每一个进程都收集了其它所有进程的数据。从参数上看,MPI_ALLGATHER和MPI_GATHER完全相同,只不过在执行效果上,对于MPI_GATHER执行结束后,只有ROOT进程的接收缓冲区有意义,MPI_ALLGATHER调用结束后所有进程的接收缓冲区都有意义,它们接收缓冲区的内容是相同的。
MPI_ALLGATHER(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm)
IN sendbuf 发送消息缓冲区的起始地址(可选数据类型)
IN sendcount 发送消息缓冲区的数据个数(整型)
IN sendtype 发送消息缓冲区的数据类型(句柄)
OUT recvbuf 接收消息缓冲区的起始地址(可选数据类型)
IN recvcount 从其它进程接收的数据个数(整型)
IN recvtype 接收消息缓冲区的数据类型(句柄)
IN comm 通信域(句柄)
//c语言的说明
int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype daatatype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
//Fortran语言的说明
MPI_ALLGATHER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT, RECVTYPE, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, COMM, IERROR
由MPI_ALLGATHER和MPI_GATHER的关系,可知MPI_ALLGATHER和MPI_GATHERV的关系。MPI_ALLGATHERV也是所有的进程都接收结果,而不是只有根进程接收结果。从每个进程发送的第j块数据将被每个进程接收,然后存放在各个进程接收消息缓冲区recvbuf的第j块。进程j的sendcount和sendtype的类型必须和其他所有进程的recvcounts[j]和recvtype相同。
MPI_ALLGATHERV(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm)
IN sendbuf 发送消息缓冲区的起始地址(可选数据类型)
IN sendcount 发送消息缓冲区的数据个数(整型)
IN sendtype 发送消息缓冲区的数据类型(句柄)
OUT recvbuf 接收消息缓冲区的起始地址(可选数据类型)
IN recvcounts 从其它进程接收的数据个数,整型数组(整型)
IN displs 接收数据的偏移,整型数组(整型)
IN recvtype 接收消息缓冲区的数据类型(句柄)
IN comm 通信域(句柄)
//c语言的说明
int MPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype daatatype, void *recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype, MPI_Comm comm)
//Fortran语言的说明
MPI_ALLGATHERV(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNTS, DISPLS, RECVTYPE, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNTS(*), DISPLS(*), RECVTYPE, COMM, IERROR
下面的程序片段实现组内每个进程都从其它进程收集100个进程,存入各自的接收缓冲区。
MPI_Comm comm;
int gsize, sendarray[100];
int *rbuf;
……
MPI_Comm_size(comm, &gsize);
rbuf = (int*)malloc(gsize*100*sizeof(int));
MPI_Allgather(sendarray, 100, MPI_INT, rbuf, 100, MPI_INT, comm);
如果采用MPI_ALLGATHERV来实现:
MPI_Comm comm;
int gsize, sendarray[100];
int root, *rbuf, stride;
int *displs, i, *rcounts;
……
MPI_Comm_size(comm, &gsize);
rbuf = (int*)malloc(gsize*stride*sizeof(int));
displs = (int*)malloc(gsize*sizeof(int));
rcounts = (int*)malloc(gsize*sizeof(int));
for(i = 0; i <