给定以下场景,我有 N 个 MPI 进程,每个进程都有一个对象。当通信阶段到来时,来自这些对象的“通常很小”的数据将被交换。一般来说,任意两个节点之间都有数据交换。
最好的策略是什么?:
- 在任何节点 X 中,为与该节点 X 建立连接的每个其他节点创建两个缓冲区,然后在对等基础上进行发送/接收。
在每个节点 X 中,创建一个缓冲区来收集所有要通信的光环数据。然后“广播”该缓冲区。
还有其他我不知道的策略吗?
对于最近邻样式的光环交换,通常最有效的实现之一是使用一组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
。
您在问题中使用光环一词表明您可能正在设置一个跨进程拆分的计算域。这是 MPI 程序中广泛应用的一种非常常见的方法。通常每个进程在其本地域上进行计算,然后所有进程与其邻居交换光环元素,然后重复直到满意。
虽然您可以创建专用缓冲区来交换光环元素,但我认为更常用的方法,当然也是明智的第一种方法,是将光环元素本身视为您正在寻找的缓冲区。例如,如果你有一个 100x100 的计算域,分布在 100 个进程中,每个进程都会得到一个 12x12 的本地域——这里我假设与 4 个正交邻居中的每一个有 1 个单元重叠,并注意全局域的边缘. 晕单元是每个本地域边界中的那些单元,在通信之前不需要将元素编组到另一个缓冲区中。
如果我正确猜到了您尝试实现的计算类型,则应该查看mpi_cart_create
其相关功能;这些旨在使设置和实施程序变得容易,其中计算步骤与相邻进程之间的通信步骤交错。网络上充斥着创建和使用这种笛卡尔拓扑的示例。
如果这是您计划的计算方式,那么mpi_bcast
绝对是错误的使用方式。MPI 广播(和类似功能)是所有进程(在给定通信器中)参与的集体操作。广播对于全球通信很有用,但光环交换是本地通信。