Pi表示具有等级i的MPI过程 X和Y是包含所选MPI_Datatype的1D向量 [aij]表示可以具有大小为0的子向量。
对于向量X,子向量[aij]中的索引j表示需要向哪个MPI进程[aij]发送。
对于向量Y,子向量[aij]中的索引i表示从哪个MPI进程[aij]接收。
从X构建Y的最佳策略是什么? 示意图如下所示。
P1 X = {[a11],[a12],[a13],...,[a1n]}; Y = {[a11],[a21],[a31],...,[an1]};
P2 X = {[a21],[a22],[a23],...,[a2n]}; Y = {[a12],[a22],[a32],...,[an2]};
P3 X = {[a31],[a32],[a33],...,[a3n]}; Y = {[a13],[a23],[a33],...,[an3]};
...
Pn X = {[an1],[an2],[an3],...,[ann]}; Y = {[a1n],[a2n],[a3n],...,[ann]};
为方便起见,选择索引编号从一开始。
编辑(根据eduffy和francis的评论):
当虚拟通信拓扑稀疏时,即当大多数索引i,j的大小([aij])= 0时,我正在使用点对点通信来执行此操作。
确定每个MPI进程将获得的NRECV接收数。这可以通过布尔FLAG =(i!= j)&&(size([aij])!= 0)的MPI_Reduce为每个进程找到。
如果FLAG为真,每个进程i执行块[aij]的非阻塞发送以处理j。
每个进程i执行非阻塞探测并从进程j接收非零大小的块[aji]。这些动态接收可以写成NRECV迭代的循环。
然而,以符合MPI标准的方式实施此策略变得越来越困难。例如,缓冲区一次只能用于一次通信(即使是多次读取的明显无害的情况;来源:Jeff Squyres article)。
更新:
我发现MPI_Alltoallv()适合于子矢量[aij]的转置。但是,当通信拓扑很稀疏时,一些文章(在互联网上找到)确实报告了可扩展性问题。最近的MPI标准(超出版本3)包括具有拓扑结构的通信器上的集体通信MPI_Neighbor_alltoallv()。