mpi中的Python多处理

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

我有一个使用多处理模块编写的python脚本,用于更快的执行。计算是令人尴尬的并行,因此效率与处理器数量成正比。现在,我想在MPI程序中使用它,该程序管理跨多台计算机的MCMC计算。这段代码调用system(),后者调用python脚本。然而,我发现,当以这种方式调用时,使用python多处理带来的效率收益就消失了

如何让python脚本在从MPI调用时保持多处理带来的速度增益

下面是一个简单的示例,它类似于我想要使用的更复杂的代码,但显示了相同的一般行为。我编写了一个名为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()
当我自己从shell运行这个程序时,使用“top”可以看到三个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
(附加说明:这是Linux Debian版本wheezy上的mpirun 1.8.1和python 2.7.3。我听说在MPI程序中并不总是允许使用system(),但在这台计算机上它已经为我工作了五年。例如,我从system()调用了基于pthread的并行代码在MPI程序中,每个线程使用100%的cpu。此外,如果您建议串行运行python脚本并在更多节点上调用它,MCMC计算涉及固定数量的链,这些链需要以同步方式移动,因此不幸的是,计算无法重新组织为w是的。

默认为将进程绑定到核心-也就是说,当它启动python junk.py进程时,它将进程绑定到它将运行的核心。这很好,并且是大多数MPI用例的正确默认行为。但在这里,每个MPI任务都会分叉更多的进程(通过多处理包),这些分叉的进程继承其父进程的绑定状态——因此它们都绑定到同一个核心,相互争斗。(顶部的“P”列将显示它们都在同一个处理器上)

如果您运行MPI-np 2,您将发现两组三个进程,每个进程位于不同的核心上,每个进程之间相互竞争

使用OpenMPI,可以通过关闭绑定来避免这种情况

mpirun -np 1 --bind-to none junk.py
或者根据跑步的最终几何图形选择其他有意义的绑定。姆皮奇有


请注意,使用mpi对子进程进行fork()调用,特别是使用infiniband互连运行的集群,但OpenMPI的mpirun/mpiexec会在不安全时向您发出警告。

所以答案是在脚本中关闭多处理?对不起,答案是哪一部分?使用--bind to none启动将避免CPU问题。至于fork的问题,OpenMPI的mpirun/mpiexec将让您知道您是否在fork不安全的情况下运行,并且您可以在出现该问题时/如果出现该问题,就解决该问题。我已确认此解决方案有效,包括简单示例和我的真实代码。非常感谢!我猜mpirun的这种行为随着openmpi版本1.7中的绑定选项而改变,否则我就看不出为什么我之前运行的一些代码会起作用。