当前位置:首页 > 并行算法讲义
ENDIF
§5.3.3 全收集 MPI_Allgather C
int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
Fortran 77
MPI_ALLGATHER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNT, RECVTYPE, COMM, IERR)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, COMM, + IERR
MPI_Allgather与MPI_Gather类似,区别是所有进程同时将数据收集到 recvbuf 中,因此称为数据全收集。
MPI_Allgather等价于依次以每个进程为根进程调用 NPROCS 次普通数据收集函数 MPI-Gather。
DO I=0, NPROCS-1
CALL MPI_GATHER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNT, RECVTYPE, I, COMM, IERR)
ENDDO
也可以认为MPI_Allgather相当于以任一进程为根进程调用一次普通收集,紧接着再对收集到的数据进行一次广播,例如:
ROOT=0
CALL MPI_GATHER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNT, RECVTYPE, ROOT, COMM, IERR)
CALL MPI_BCAST(RECVBUF, RECVCOUNT*NPROCS, RECVTYPE, ROOT, + COMM, IERR)
§5.3.4 不同长度数据块的全收集 MPI_Allgatherv C
int MPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcounts, int *displs,
MPI_Datatype recvtype, MPI_Comm comm)
Fortran 77
MPI_ALLGATHERV(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNTS, DISPLS, RECVTYPE, COMM, IERR)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNTS(*), DISPLS(*), + RECVTYPE, COMM, IERR
MPI_Allgatherv用于不同长度数据块的全收集。它的参数与MPI_Gatherv类似 MPI_Allgatherv等价于依次以每个进程为根进程调用 NPROCS 次 MPI_Gatherv。
DO I=0, NPROCS-1
CALL MPI_GATHERV(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNTS, DISPLS, RECVTYPE, I, COMM, IERR)
ENDDO
也可以认为MPI_Allgatherv相当于以任一进程为根进程调用一次普通收集,紧接着再对收集到的数据进行一次广播,例如
ROOT=0
CALL MPI_GATHERV(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNTS, DISPLS, RECVTYPE, ROOT, COMM, IERR)
CALL MPI_TYPE_INDEXED(NPROCS, RECVCOUNTS, DISPLS, RECVTYPE, + NEWTYPE, IERR)
CALL MPI_TYPE_COMMIT(NEWTYPE, IERR)
CALL MPI_BCAST(RECVBUF, 1, NEWTYPE, ROOT, COMM, IERR) CALL MPI_TYPE_FREE(NEWTYPE, IERR)
§5.4 数据散发
数据散发指根进程将一个大的数据块分成小块分别散发给各个进程 (包括根进程自己) 它是数据收集的逆操作。
§5.4.1 散发相同长度数据块 MPI_Scatter C
int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf,
int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
Fortran 77
MPI_SCATTER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNT, RECVTYPE, ROOT, COMM, IERR)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, + COMM, IERR
根进程 root 的 sendbuf中包含有NPROCS个连续存放的数据块,每个数据块包含 sendcount 个类型为 sendtype 的数据, NPROCS 为通信器中的进程数。根进程将这些数据块按进程的序号依次分发给各个进程 (包括根进程自己)。 参数 sendbuf,sendcount 和 sendtype 仅对根进程有意义。
假设 MYRANK 为进程号,则 MPI_Scatter 相当于:
IF ( MYRANK .EQ. ROOT ) THEN DO I=0, NPROCS-1
CALL MPI_SEND( SENDBUF + I*SENDCOUNT*extent(SENDTYPE), + SENDCOUNT, SENDTYPE, I, ...)
ENDDO ENDIF
CALL MPI_RECV(RECVBUF, RECVCOUNT, RECVTYPE, ROOT, ...)
§5.4.2 散发不同长度数据块 MPI Scatterv C
int MPI_Scatterv(void *sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype, void *recvbuf, int recvcount,
MPI_Datatype recvtype, int root, MPI_Comm comm)
Fortran 77
MPI_SCATTERV(SENDBUF, SENDCOUNTS, DISPLS, SENDTYPE, + RECVBUF, RECVCOUNT, RECVTYPE, ROOT, COMM, IERR)
INTEGER SENDCOUNTS(*), DISPLS(*), SENDTYPE, RECVCOUNT,
+ RECVTYPE, ROOT, COMM, IERR .
与MPI_Scatter类似,但允许发送的每个数据块的长度不同并且在 sendbuf 中不一定连续存放。sendbuf, sendtype, sendcounts 和 displs 仅对根进程有意义。数组 sendcounts 和 displs 的元素个数等于进程数,它们分别给出发送给每个进程的数据长度和位移 (以 sendtype 为单位)。
假设 NPROCS为通信器中的进程数, MYRANK 为进程号,则 MPI_Scatterv相当于
INTEGER DISPLS(0:NPROCS-1), SENDCOUNTS(0:NPROCS-1) ... ...
IF ( MYRANK .EQ. ROOT ) THEN DO I=0, NPROCS-1
CALL MPI_SEND( SENDBUF + DISPLS(I)*extent(SENDTYPE), + SENDCOUNTS(I), SENDTYPE, I, ...)
ENDDO ENDIF
CALL MPI_RECV(RECVBUF, RECVCOUNT, RECVTYPE, ROOT, ...)
§5.5 全部进程对全部进程的数据散发收集 每个进程散发自己的一个数据块,并且收集拼装所有进程散发过来的数据块 我们称该操作为数据的 “全散发收集”,它既可以被认为是数据全收集的扩展,也可以被认为是数据散发的扩展。 §5.5.1 相同数据长度的全收集散发 MPI_Alltoall C
int MPI_Alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
Fortran 77
MPI_ALLTOALL(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, + RECVCOUNT, RECVTYPE, COMM, IERR)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, COMM, + IERR
笫i个进程将 sendbuf 中的笫j块数据发送至笫j个进程的recvbuf的笫i个位置,i, j = 0, . . . , NPROCS-1 (NPROCS 为进程数)。sendbuf 和 recvbuf 均由 NPROCS个连续存放的数据块
共分享92篇相关文档