首页 文章

mpi中的Python多处理

提问于
浏览
12

我有一个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()

当我自己从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进程占用cpu的33%,总体而言,它需要大约三倍的运行时间 . 使用-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,Linux Debian版本的python 2.7.3喘息 . 我听说系统()并不总是允许在MPI程序中,但它在这台计算机上过去五年一直在为我工作 . 例如,我在MPI程序中调用了来自system()的基于pthread的并行代码,并且根据需要使用100%的cpu用于每个线程 . 另外,如果你打算建议在串行中运行python脚本,只是在更多节点上调用它... MCMC计算涉及需要以同步方式移动的固定数量的链,因此遗憾的是,计算不能以这种方式重组 . )

1 回答

  • 9

    OpenMPI's mpirun, v1.7 and later,默认绑定进程到核心 - 也就是说,当它启动python junk.py进程时,它将它绑定到它将运行的核心 . 那个's fine, and the right default behaviour for most MPI use cases. But here each MPI task is then forking more processes (through the multiprocessing package), and those forked processes inherit the binding state of their parent - so they'全部绑定到同一个核心,相互争斗 . (顶部的"P"列将显示它们都在同一个处理器上)

    如果你mpirun -np 2,你会发现两组三个进程,每个进程在不同的核心上,每个进程在它们之间竞争 .

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

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

    或者选择其他一些在运行的最终几何形状下有意义的绑定 . MPICH有similar options with hydra .

    请注意带有mpi isn't always safe or supported的子进程的fork(),特别是对于使用infiniband互连运行的集群,但OpenMPI 's mpirun/mpiexec will warn you if it isn' t安全 .

相关问题