在 MPI 进程之间交换数据(晕)

Posted

技术标签:

【中文标题】在 MPI 进程之间交换数据(晕)【英文标题】:Exchange Data Between MPI processes (halo) 【发布时间】:2013-07-08 22:50:46 【问题描述】:

鉴于以下情况,我有 N 个 MPI 进程,每个进程都有一个对象。当通信阶段到来时,来自这些对象的“通常很小”的数据将被交换。 一般来说,任意两个节点之间都有数据交换。

什么是最好的策略?:

在任何节点 X 中,为与该节点 X 建立连接的每个其他节点创建两个缓冲区。然后在对等基础上进行发送/接收。

在每个节点X中,创建一个缓冲区来收集所有要通信的光环数据。然后“bcast”那个缓冲区。

还有其他我不知道的策略吗?

【问题讨论】:

【参考方案1】:

对于最近邻样式的光环交换,通常最有效的实现之一是使用一组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,即可执行整个多维光环交换。

【讨论】:

【参考方案2】:

您在问题中使用的词 halo 表明您可能正在设置一个跨进程拆分的计算域。这是 MPI 程序中广泛应用的一种非常常见的方法。通常每个进程在其本地域上进行计算,然后所有进程与其邻居交换光环元素,然后重复直到满意。

虽然您可以创建专用缓冲区来交换光环元素,但我认为更常用的方法,当然也是明智的第一种方法,是将光环元素本身视为您正在寻找的缓冲区。例如,如果你有一个 100x100 的计算域,分布在 100 个进程中,每个进程都会得到一个 12x12 的本地域——这里我假设与 4 个正交邻居中的每一个有 1 个单元重叠,并注意全局域的边缘.晕细胞每个局部域边界中的那些细胞,在通信之前无需将元素编组到另一个缓冲区中。

如果我猜对了您尝试实现的计算类型,您应该查看mpi_cart_create 及其相关函数;这些旨在使设置和实施程序变得容易,其中计算步骤与相邻进程之间的通信步骤交错。网络上充斥着创建和使用此类笛卡尔拓扑的示例。

如果这是您计划的计算方式,那么mpi_bcast 绝对是错误的使用方式。 MPI 广播(和类似功能)是所有进程(在给定通信器中)参与的集体操作。广播对于全球通信很有用,但光环交换是本地通信。

【讨论】:

以上是关于在 MPI 进程之间交换数据(晕)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用一次广播在 MPI 中传输不同类型的向量

在 UNIX 进程之间交换适度大量数据的最佳方式是啥?

MPI 笛卡尔拓扑:MPI_Neighbor_alltoall 发送错误数据

PPI通讯和MPI通讯是啥概念?

如何在 Linux 中的进程之间交换二进制数据

mpi4py:空闲内核显着放缓