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