MPI_GATHER(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root , comm)
INsendbuf发送消息缓冲区的起始地址(可选数据类型)
INsendcount发送消息缓冲区中的数据个数(整型)
INsendtype发送消息缓冲区中的数据类型(句柄)
OUTrecvbuf 接收消息缓冲区的起始地址(可选数据类型)
INrecvcount待接收的元素个数(整型,仅对于根进程有意义)
INrecvtype接收元素的数据类型(句柄,仅对于根进程有意义)
INroot接收进程的序列号(整型)
INcomm通信域(句柄)
int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype,
int root, MPI_Comm comm)
MPI_GATHER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT,
RECVTYPE,ROOT, COMM, IERROR)
  <type> SENDBUF(*), RECVBUF(*)
  INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM,
IERROR

收集MPI_GATHER是典型的多对一通信的例子。在收集调用中,每个进程(包括根进程本身)将其发送缓冲区中的消息发送到根进程,根进程根据发送进程的进程标识的序号即进程的rank值,将它们各自的消息依次存放到自已的消息缓冲区中。和广播调用不同的是,广播出去的数据都是相同的,但对于收集操作,虽然从各个进程收集到的数据的个数必须相同,但从各个进程收集到的数据一般是互不相同的。其结果就象一个进程组中的N个进程(包括根进程在内)都执行了一个发送调用,同时根进程执行了N次接收调用。
对于所有非根进程,接收消息缓冲区被忽略,但是各个进程必须提供这一参数。
收集调用每个进程的发送数据个数sendcount和发送数据类型sendtype都是相同的,都和根进程中接收数据个数recvcount和接收数据类型recvtype相同。注意根进程中指定的接收数据个数是指从每一个进程接收到的数据的个数,而不是总的接收个数。
此调用中的所有参数对根进程来说都是有意义的,而对于其它进程只有sendbuf、sendcount、sendtype、root和comm是有意义的。其它的参数虽然没有意义,但是却不能省略。root和comm在所有进程中都必须是一致的。

数据收集

MPI_GATHERV(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs,recvtype,
root, comm)
INsendbuf发送消息缓冲区的起始地址(可选数据类型)
INsendcount发送消息缓冲区中的数据个数(整型)
INsendtype发送消息缓冲区中的数据类型(句柄)
OUTrecvbuf接收消息缓冲区的起始地址(可选数据类型,仅对于根进程有意义)
INrecvcounts整型数组(长度为组的大小), 其值为从每个进程接收的数据个数
IN displs整数数组,每个入口表示相对于recvbuf的位移
INrecvtype 接收消息缓冲区中数据类型 (句柄)
INroot接收进程的标识号(句柄)
INcomm通信域(句柄)
int MPI_Gatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf,
int *recvcounts, int *displs, MPI_Datatype recvtype, int root, MPI_Comm comm)
MPI_GATHERV(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNTS,
DISPLS, RECVTYPE, ROOT, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNTS(*), DISPLS(*), RECVTYPE,
ROOT, COMM, IERROR

MPI_GATHERV和MPI_GATHER的功能类似,也完成数据收集的功能,但是它可以从不同的进程接收不同数量的数据。为此,接收数据元素的个数recvcounts是一个数组,用于指明从不同的进程接收的数据元素的个数。根从每一个进程接收的数据元素的个数可以不同,但是发送和接收的个数必须一致。除此之外,它还为每一个接收消息在接收缓冲区的位置提供了一个位置偏移displs数组,用户可以将接收的数据存放到根进程消息缓冲区的任意位置。也就是说,MPI_GATHERV明确指出了从不同的进程接收数据元素的个数以及这些数据在ROOT的接收缓冲区存放的起始位置,这是它相对于MPI_GATHER灵活的地方,也是比MPI_GATHER复杂的地方。
此调用中的所有参数对根进程来说都是有意义的,而对于其它的进程只有sendbuf、sendcount、sendtype、root和comm是有意义的。参数root和comm在所有进程中都必须是一致的。


下面的程序片段实现从进程组中的每个进程收集100个整型数送给根进程。

MPI_Comm comm;
int gsize,sendarray[100];
int root,*rbuf;
......
MPI_Comm_size(comm,&gsize);
rbuf=(int *)malloc(gsize*100*sizeof(int));
MPI_Gather(sendarray,100,MPI_INT,rbuf,100,MPI_INT,root,comm);