我有一个集群,但一直受困于它和mpi4py。我的代码很复杂,MPI传输数据失败。
为了使事情更清楚,我编写了一个简单的“ hello world”代码,该代码仅在节点之间传输大型数组。
数组以0初始化,然后填充来自另一个节点的数组。

import dill
from mpi4py import MPI
MPI.pickle.__init__(dill.dumps, dill.loads)

comm = MPI.COMM_WORLD
rank = comm.rank

import numpy as np

for k in range(5):
    if rank == 0:
        # node 0 sends hi to other nodes
        for i in range(1, comm.size):
            msg = np.ones(10000000, np.double)
            comm.Send([msg, MPI.DOUBLE], dest=i, tag=0)
    else:
        # other nodes receive hi
        msgin = np.zeros(10000000, np.double)
        comm.Recv([msgin, MPI.DOUBLE], source=0, tag=0)
        with open('solution1.txt', 'a') as f:
            f.write(f'{rank} hi, {msgin[:10]} {np.average(msgin)}\n')
        # and then send reply to 0 node
        msgout = np.ones(10000000)
        comm.Send([msgout, MPI.DOUBLE], dest=0, tag=1)

    if rank == 0:
        # node 0 receives replies
        for i in range(1, comm.size):
            msgin = np.zeros(10000000, np.double)
            comm.Recv([msgin, MPI.DOUBLE], tag=1, source=i)
            with open('solution1.txt', 'a') as f:
                f.write(f'{rank} reply, {msgin[:10]} {np.average(msgin)}\n')




结果如下:

1 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
2 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
3 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
4 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
5 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
1 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
2 reply [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
3 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
4 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
5 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
1 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
2 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
3 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
4 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
5 hi [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 1.0
1 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
2 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
3 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
4 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
5 reply [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08
1 hi [1. 1. 1. 1. 1. 1. 0. 0. 0. 0.] 6e-08


如您所见,偶尔只传输6个double值,而不是10000000。
此日志不完整-所有后续消息也只有6个值。
有趣的是,结果是可重复的:节点2首先总是以正确的消息答复,而其他所有节点都以错误的消息答复。

该代码可以在同一集群的单个节点上完美运行。它还可以完美地在Google Cloud中运行(每个节点32个核心,共6个)。
我尝试了不同的技巧并获得了相同的结果:


将发送/接收替换为发送/接收+等待
与标准泡菜和莳萝泡菜一起使用发送/接收。该代码无法解码泡菜数据。
尝试过openmpi 2.1.1、4.0.1和Intel MPI库
尝试从英特尔修复:


export I_MPI_SHM_LMT=shm


网络设置可能有问题,但我真的不知道该怎么办。

该设置是一个多节点群集,在2-1超额订阅的胖树中具有Mellanox 4x FDR Infiniband互连。 24个节点的集合具有进入大型核心Infiniband交换机的12个上行链路。每个节点具有64 GiB的4通道2133 MHz DDR4 SDRAM(68 GB /秒)内存;两个Intel Xeon E5-2670 v3(Haswell)CPU。

最佳答案

在我的设置中,我发现始终使用相同的缓冲区接收结果很有用。

因此,可以尝试在代码中尽早声明一次msgin = np.zeros(10000000, np.double)并一次又一次地使用它。每次收到消息时,您都可以执行msgin.fill(np.nan)来“清除”缓冲区。

我不知道为什么它对我有用,但是问题似乎消失了。

祝好运!

关于python - MPI4py的MPI数据传输错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57979653/

10-16 21:28