鉴于以下场景,我有N个MPI进程,每个进程都有一个对象.当通信阶段到来时,将交换来自这些对象的"通常很小"的数据.通常,任何两个节点之间都存在数据交换.
什么是最好的策略?:
在每个节点X中,创建一个缓冲区以收集要传递的所有光环数据.然后"bcast"缓冲.
还有其他我不知道的策略吗?
Hri*_*iev 11
对于最近邻风格的光环交换,通常最有效的实现之一是使用一组MPI_Sendrecv调用,通常每个维度有两个:
半步骤 - 向正方向传输数据:每个等级从左边的一个接收到左边的光环,并将数据发送到右边的等级
+-+-+---------+-+-+ +-+-+---------+-+-+ +-+-+---------+-+-+
--> |R| | (i,j-1) |S| | --> |R| | (i,j) |S| | --> |R| | (i,j+1) |S| | -->
+-+-+---------+-+-+ +-+-+---------+-+-+ +-+-+---------+-+-+
Run Code Online (Sandbox Code Playgroud)
(S指定正在传送的本地数据的一部分,同时R指定正在接收数据的光环,(i,j)是过程网格中等级的坐标)
半步骤二 - 向负方向传输数据:每个等级从右边的一个接收到右边的光环并将数据发送到左边的等级
+-+-+---------+-+-+ +-+-+---------+-+-+ +-+-+---------+-+-+
<-- |X|S| (i,j-1) | |R| <-- |X|S| (i,j) | |R| <-- |X|S| (i,j+1) | |R| <--
+-+-+---------+-+-+ +-+-+---------+-+-+ +-+-+---------+-+-+
Run Code Online (Sandbox Code Playgroud)
(X是前一半步骤中已经填充的光环区域的一部分)
大多数交换网络支持多个同时双向(全双工)通信,并且整个交换的延迟是
上述两个半步骤的重复次数与域分解的维数一样多.
在该标准的3.0版本中,该过程甚至更加简化,该标准引入了所谓的邻居集体通信.可以使用单个调用来执行整个多维光环交换MPI_Neighbor_alltoallw.
您在问题中使用单词halo表明您可能正在设置一个跨进程分割的计算域.这是MPI程序中广泛应用的一种非常常见的方法.通常,每个进程计算其本地域,然后所有进程与其邻居交换光环元素,然后重复直到满意为止.
虽然你可以创建用于交换光环元素的专用缓冲区,但我认为更常用的方法,当然是一种明智的第一种方法,就是将光环元素本身视为你正在寻找的缓冲区.例如,如果你有一个100x100计算域分为100个进程,每个进程得到一个12x12本地域 - 这里我假设与4个正交邻居中的每一个都有1个单元重叠,并注意全局域的边缘.晕圈单元是每个局部域边界中的那些单元,并且在通信之前不需要将元素编组到另一个缓冲器中.
如果我正确地猜到了你想要实现的计算类型,你应该看看mpi_cart_create它及其相关的函数; 这些设计旨在使设置和实现程序变得容易,其中计算步骤与相邻进程之间的通信步骤交错.网络充斥着创建和使用此类笛卡尔拓扑的示例.
如果这是您正在计划的计算方式,那么使用mpi_bcast它绝对是错误的.MPI广播(和类似功能)是集体操作,其中所有进程(在给定的通信器中)参与.广播对全球通信很有用,但光环交换是本地通信.