mpi - MPI_Allgather 和 MPI_Alltoall 函数之间的区别?

标签 mpi

MPI 中的 MPI_Allgather 和 MPI_Alltoall 函数之间的主要区别是什么?

我的意思是有人可以给我举例说明 MPI_Allgather 有帮助而 MPI_Alltoall 没有帮助吗?反之亦然。

我无法理解主要区别?看起来在这两种情况下,所有进程都将 send_cnt 元素发送到参与通信器的每个其他进程并接收它们?

谢谢

最佳答案

一图胜千言,这里有几张ASCII艺术图:

rank    send buf                        recv buf
----    --------                        --------
 0      a,b,c         MPI_Allgather     a,b,c,A,B,C,#,@,%
 1      A,B,C        ---------------->  a,b,c,A,B,C,#,@,%
 2      #,@,%                           a,b,c,A,B,C,#,@,%

这只是常规的 MPI_Gather ,只有在这种情况下所有进程都会收到数据 block ,即操作是无根的。

rank    send buf                        recv buf
----    --------                        --------
 0      a,b,c          MPI_Alltoall     a,A,#
 1      A,B,C        ---------------->  b,B,@
 2      #,@,%                           c,C,%

(a more elaborate case with two elements per process)

rank    send buf                        recv buf
----    --------                        --------
 0      a,b,c,d,e,f    MPI_Alltoall     a,b,A,B,#,@
 1      A,B,C,D,E,F  ---------------->  c,d,C,D,%,$
 2      #,@,%,$,&,*                     e,f,E,F,&,*

(如果每个元素都按发送它的排名着色,看起来会更好,但是......)

MPI_Alltoall组合使用 MPI_ScatterMPI_Gather - 每个进程中的发送缓冲区被分割,如MPI_Scatter然后每一列的 block 由各自的进程收集,其等级与 block 列的编号匹配。 MPI_Alltoall也可以看作是全局转置操作,作用于数据 block 。

这两种操作是否存在可以互换的情况?要正确回答这个问题,只需简单分析一下发送缓冲区和接收缓冲区的数据大小:

operation      send buf size      recv buf size
---------      -------------      -------------
MPI_Allgather  sendcnt            n_procs * sendcnt
MPI_Alltoall   n_procs * sendcnt  n_procs * sendcnt

接收缓冲区大小实际上是n_procs * recvcnt ,但 MPI 要求发送的基本元素数量应等于接收的基本元素数量,因此如果 MPI_All... 的发送和接收部分使用相同的 MPI 数据类型,然后recvcnt必须等于sendcnt .

很明显,对于相同大小的接收数据,每个进程发送的数据量是不同的。为了使两个操作相等,一个必要条件是两种情况下发送的缓冲区的大小相等,即 n_procs * sendcnt == sendcnt ,只有在 n_procs == 1 时才有可能,即如果只有一个进程,或者如果 sendcnt == 0 ,即根本没有发送任何数据。因此,实际上不存在两种操作真正可以互换的可行情况。但可以模拟MPI_AllgatherMPI_Alltoall通过重复n_procs乘以发送缓冲区中的相同数据(正如 Tyler Gill 已经指出的那样)。这是 MPI_Allgather 的操作使用单元素发送缓冲区:

rank    send buf                        recv buf
----    --------                        --------
 0      a             MPI_Allgather     a,A,#
 1      A            ---------------->  a,A,#
 2      #                               a,A,#

这里使用 MPI_Alltoall 实现了相同的效果:

rank    send buf                        recv buf
----    --------                        --------
 0      a,a,a          MPI_Alltoall     a,A,#
 1      A,A,A        ---------------->  a,A,#
 2      #,#,#                           a,A,#

相反的情况是不可能的 - 无法模拟 MPI_Alltoall 的 Action 与 MPI_Allgather在一般情况下。

关于mpi - MPI_Allgather 和 MPI_Alltoall 函数之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15049190/

相关文章:

algorithm - MPI+CUDA 比纯 MPI 有什么优势?

c++ - 简单的分布式图 BGL 示例

io - Fortran MPI 代码打开具有相同单元号的不同文件

c++ - 具有灵活大小的结构的 MPI 派生数据类型

c - 最适合 "block decomposition"的 MPI_Datatype ?

c++ - MVAPICH 在 MPI_Send 上挂起大于急切阈值的消息

c++ - 将 MPI 与 c++11 和 CUDA 相结合

c++ - 如何使用 boost MPI 出现死锁情况(我使用 MPICH 编译器)?

algorithm - 使用 MPI 在 2D 域上并行化

multithreading - 在指定数量的内核上运行MPI程序