我有一个使用多处理模块编写的python脚本,可以更快地执行。计算是令人尴尬的并行,因此效率与处理器数量成比例。现在,我想在MPI程序中使用它,它在多台计算机上管理一个MCMC计算。此代码调用了System(),后者调用了Python脚本。然而,我发现当它以这种方式被调用时,使用Python多处理所获得的效率将消失。
当从MPI调用时,如何让我的python脚本保持多处理带来的速度提升?
下面是一个简单的例子,它类似于我想要使用的更复杂的代码,但显示了相同的一般行为。我编写了一个名为junk.py的可执行python脚本。

#!/usr/bin/python
import multiprocessing
import numpy as np

nproc = 3
nlen = 100000


def f(x):
    print x
    v = np.arange(nlen)
    result = 0.
    for i, y in enumerate(v):
        result += (x+v[i:]).sum()
    return result


def foo():
    pool = multiprocessing.Pool(processes=nproc)
    xlist = range(2,2+nproc)
    print xlist
    result = pool.map(f, xlist)
    print result

if __name__ == '__main__':
    foo()

当我使用“top”从shell本身运行它时,我可以看到三个Python进程,每个进程在我的16核机器上占用了100%的CPU。
node094:mpi[ 206 ] /usr/bin/time junk.py
[2, 3, 4]
2
3
4
[333343333400000.0, 333348333450000.0, 333353333500000.0]
62.68user 0.04system 0:21.11elapsed 297%CPU (0avgtext+0avgdata 16516maxresident)k
0inputs+0outputs (0major+11092minor)pagefaults 0swaps

但是,如果我用mpirun调用这个函数,每个python进程占用33%的CPU,总的来说运行时间大约是它的三倍。使用-np 2或更多调用会导致更多进程,但不会加快任何计算速度。
node094:mpi[ 208 ] /usr/bin/time mpirun -np 1 junk.py
[2, 3, 4]
2
3
4
[333343333400000.0, 333348333450000.0, 333353333500000.0]
61.63user 0.07system 1:01.91elapsed 99%CPU (0avgtext+0avgdata 16520maxresident)k
0inputs+8outputs (0major+13715minor)pagefaults 0swaps

(附加说明:这是mpirun 1.8.1,python 2.7.3在linux debian版本的weezy上。我听说在MPI程序中并不总是允许使用System(),但在这台计算机上,它已经为我工作了五年。例如,我在MPI程序中从System()调用了一个基于pthread的并行代码,并且它根据需要为每个线程使用100%的CPU。另外,如果您打算建议以串行方式运行python脚本,并在更多节点上调用它……MCMC计算涉及固定数量的链,这些链需要以同步方式移动,因此不幸的是,无法以这种方式重新组织计算。)

最佳答案

OpenMPI's mpirun, v1.7 and later,默认为将进程绑定到核心-即,当它启动python junk.py进程时,它将其绑定到将运行的核心。这很好,对于大多数MPI用例来说都是正确的默认行为。但是在这里,每个MPI任务都会分叉更多的进程(通过多处理包),而这些分叉的进程继承了其父进程的绑定状态——所以它们都绑定到同一个核心,在它们之间进行斗争。(顶部的“P”列将显示它们都在同一处理器上)
如果您mpirun-np 2,您将发现两组三个进程,每个进程位于不同的核心上,每个进程彼此竞争。
使用OpenMPI,可以通过关闭绑定来避免这种情况,

mpirun -np 1 --bind-to none junk.py

或者选择一些其他绑定,考虑到运行的最终几何图形,这是有意义的。MPICH有similar options with hydra
请注意,使用mpiisn't always safe or supported的子进程的fork()ing,特别是使用Infiniband互连运行的集群,但如果不安全,OpenMPI的mpirun/mpiexec将警告您。

关于python - mpi中的Python多处理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25772289/

10-11 22:57
查看更多