当使用mpi4py时并行启动子进程时,速度会降低

问题描述 投票:0回答:1

使用mpi4py,我正在运行一个python程序,该程序并行启动多个fortran进程,从SLURM脚本开始使用(例如):

mpirun -n 4 python myprog.py

但是已经注意到myprog.py需要更长的时间来运行所请求的任务数量越多,例如。运行myprog.py(以下代码仅显示程序的mpi部分):

comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()

data = None

if rank == 0:
    data = params

recvbuf = np.empty(4, dtype=np.float64) 
comm.Scatter(data, recvbuf, root=0)

py_task(int(recvbuf[0]), recvbuf[1], recvbuf[2], int(recvbuf[3]))

在单个recvbuf阵列上使用mpirun -n 1 ...需要3分钟 - 同时在四个recvbuf阵列上运行(预期并行),在使用mpirun -n 4的四个处理器上运行大约需要5分钟。但是,我预计单处理器和四处理器情况的运行时间大致相等。

py_task实际上是一个python包装器,用于启动fortran程序:

subprocess.check_call(cmd) 

subprocess.check_call(cmd)和mpi4py包之间似乎存在一些交互,它阻止代码并行正常运行。

我查了一下这个问题,但似乎找不到任何有帮助的东西。是否有任何针对此问题的修复/详细说明解释此处发生了什么/关于如何在此代码中找出瓶颈原因的建议?

附加说明:

此管道已经适应了“joblib import Parallel”的mpi4py,其中没有先前并行运行的subprocess.check_call()问题,这就是为什么我怀疑这个问题与子进程和mpi4py之间的交互有关。

python subprocess mpi4py
1个回答
0
投票

减速最初是通过添加:

export SLURM_CPU_BIND = none

发布工作的slurm脚本。

虽然以上确实提供了临时解决方案,但问题实际上要深刻得多,我将在此提供一个非常基本的描述。

1)我卸载了我用conda安装的mpi4py,然后重新加载了英特尔MPI(我们的计算集群推荐的MPI版本)。在SLURM脚本中,我然后将python程序的启动更改为:

srun python my_prog.py。

并删除了上面的导出...行,并删除了减速。

2)发现另一次减速,一次发射> 40个任务。这是由于:

每次启动基于fortran的子流程时,文件系统都会要求初始资源(例如,将文件作为参数提供给程序)。在我的情况下,同时启动了大量任务,每个文件可能大约500mb,这可能超过了集群文件系统的IO功能。这导致从启动每个子进程的速度减慢引入程序的大量开销。

以前的并行化joblib实现一次只使用最多24个核心,然后对文件系统的请求没有明显的瓶颈 - 因此之前没有发现性能问题。

对于2),我发现最好的解决方案是显着重构我的代码,以最小化启动的子进程数。一个非常简单的修复,但在找到文件系统上的资源请求瓶颈之前我还没有意识到。

(最后,我还要补充说,通常不建议在线使用mpi4py中的子进程模块,多处理模块首选用于单节点。)

© www.soinside.com 2019 - 2024. All rights reserved.