我有一个集群,但一直受困于它和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/