我想知道是否有人看到我遇到的问题与mpi4py:
代码包含一个任务列表,它发送给从属服务器并生成一个可在特定配置上运行的fortran可执行文件。 fortran代码执行得非常快,但是在每个任务之间调用它时会有相当大的影响。我不确定是什么导致它,但如果有人能发现问题,这将是一个很大的帮助。代码也可以在串行模式下运行配置,依次使用它们而不是使用mpi4py,并且在该模式下没有任何挂起。
连续的时间是:
real 0m12.323s
user 0m45.468s
sys 0m1.490s
而对于下面的mpi4py版本:
real 2m2.796s
user 4m1.602s
sys 2m43.595s
我注意到代码运行时潜伏着很多hydra_pmi_proxy僵尸:
29770 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29772 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29784 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29795 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29796 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29797 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29810 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29815 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29820 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29825 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29830 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29835 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29836 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29837 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29838 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29855 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29860 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29865 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29866 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29878 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29880 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.01 hydra_pmi_proxy
29886 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29887 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29888 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29889 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29906 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29911 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29912 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29913 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29926 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29927 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
29928 cor22 20 0 0 0 0 Z 0.0 0.0 0:00.00 hydra_pmi_proxy
我不确定为什么会这样。
我曾经认为这可能是由于fortran代码写入stdout而导致的一些i / o问题,但是当我更改代码以使其不再具有效果时。似乎fortran代码执行并完成,并且挂起在python脚本中的某处。代码在其中一个本地集群的节点上运行得更好,它最终会在我的本地计算机上运行它,但是使用mpi4py的想法是为了加快速度,这会减慢它们的速度,所以我很抓我的头......
所有的print语句都在super_master.py的循环结束时吐出来,而不是随着运行的进行,这让我感到困惑
下面是代码的虚拟版本,它具有与我运行的相同的问题:
mpirun -np 1 python3 ./super_master.py
感谢任何见解和对不起的长篇文章感到抱歉!
super_master.py:
#! /usr/bin/env python3
import os
from mpi4py import MPI
import sys
comm = MPI.COMM_WORLD
for x in range(0, 3):
new_comm=comm.Spawn(sys.executable,args=["master.py"],maxprocs=1)
new_comm.Barrier()
new_comm.Disconnect()
print("finnished run ",x)
os.system('{}'.format('rm */*out*'))
master.py:
#! /usr/bin/env python3
from mpi4py import MPI
import numpy as np
import sys
import os
import time
comm = MPI.COMM_WORLD
rank = MPI.COMM_WORLD.Get_rank()
commp = MPI.Comm.Get_parent()
processes=4
tasks=([StopIteration] * (processes))+[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
new_comm=comm.Spawn("/PATH/TO/slave.py", args=[],maxprocs=processes)
status=MPI.Status()
while tasks:
new_comm.recv(source=MPI.ANY_SOURCE, status=status)
data=tasks.pop()
print("on master received source: ",status.Get_source())
print("On master sending: ",data," to:",status.Get_source())
new_comm.send(obj=data,dest=status.Get_source())
print("On master sent: ",data," to:",status.Get_source())
print("Finished All",rank)
new_comm.Barrier()
print("after barrier",rank)
print("rank", rank,"task",tasks)
commp.Barrier()
commp.Disconnect()
slave.py:
#! /usr/bin/env python3
from mpi4py import MPI
import numpy as np
import sys
import os
import time
comm = MPI.Comm.Get_parent()
rank = comm.Get_rank()
cwd=os.getcwd()
print("slave", rank," entering loop")
for task in iter(lambda: comm.sendrecv(data,dest=0), StopIteration):
print("slave ", rank," recvd data", task)
print("slave ", rank," going to sleep")
directory=os.path.join(cwd,str(task))
os.chdir(directory)
info = MPI.Info.Create()
info.update({"wdir": directory})
print("before spawn in slave:", rank)
new_comm=MPI.COMM_SELF.Spawn("/PATH/TO/FORTRAN_EXECUTABLE",
args=[],maxprocs=4,info=info)
print("after spawn in slave:", rank)
new_comm.Barrier()
new_comm.Disconnect()
info.Free()
os.system('{}'.format('sleep '+str(task*1.5)))
os.chdir(cwd)
comm.Barrier()
comm.Disconnect()
修改
嗨,大家好,
似乎在我的本地机器上,当fortran代码运行时,生成的python进程会进入休眠状态:
17530 cor22 20 0 190044 25868 10056 S 0.0 0.0 0:01.83 python3
17531 cor22 20 0 189924 25832 10020 S 0.0 0.0 0:01.33 python3
17532 cor22 20 0 189920 25844 10040 S 0.0 0.0 0:01.24 python3
17533 cor22 20 0 190036 25832 10024 S 0.0 0.0 0:01.82 python3
17534 cor22 20 0 190040 25832 10024 S 0.0 0.0 0:01.32 python3
似乎在群集上没有发生。这似乎是减缓事情的原因。如果有人对如何防止这种行为有任何想法,我会非常渴望听到它!
在群集上,如果任务列表很大,我可以获得相当好的加速比序列版本。如果任务列表很小(<20左右)没有太大的加速,看起来事情在它第一次启动时会稍微停留一下,但如果列表足够大,它会在任务列表中移动它回到正轨。我不知道为什么会这样,但如果有人有任何建议我想听听他们。
16个cpu集群上的计时,用于运行4个生成的进程,每个进程都有一个从属服务器在4个进程上运行fortran代码:
Tasks mpi4py serial
10 0m28.109s 0m30.472s
20 0m47.166s 1m6.380s
30 0m48.586s 1m38.161s
40 0m56.258s 2m10.056s
50 1m5.508s 2m10.056s
100 1m31.854s 5m22.126s
200 2m18.955s 9m4.022s