mpi 中的 Python 多处理

标签 python multiprocessing mpi

我有一个使用多处理模块编写的 python 脚本,用于更快地执行。计算是令人尴尬的并行,因此效率与处理器数量成比例。现在,我想在 MPI 程序中使用它,该程序管理跨多台计算机的 MCMC 计算。此代码调用了调用 python 脚本的 system()。但是,我发现当以这种方式调用它时,使用 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 版本上的 mpirun 1.8.1,python 2.7.3 喘不过气来。我听说 system() 在 MPI 程序中并不总是被允许,但它在过去五年中一直为我工作这台计算机。例如,我在 MPI 程序中从 system() 调用了一个基于 pthread 的并行代码,并且它根据需要为每个线程使用了 100% 的 cpu。此外,如果您要建议运行 python 脚本串行并在更多节点上调用它...MCMC 计算涉及固定数量的链,这些链需要以同步方式移动,因此不幸的是无法以这种方式重新组织计算。)

最佳答案

OpenMPI's mpirun, v1.7 and later ,默认将进程绑定(bind)到核心——也就是说,当它启动 python junk.py 进程时,它将它绑定(bind)到它将运行的核心。这很好,并且是大多数 MPI 用例的正确默认行为。但是在这里,每个 MPI 任务都会 fork 更多的进程(通过 multiprocessing 包),而那些 fork 的进程继承了它们父进程的绑定(bind)状态——所以它们都绑定(bind)到同一个核心,相互争斗。 (顶部的“P”列将向您显示它们都在同一处理器上)

如果你 mpirun -np 2,你会发现两组三个进程,每个进程在不同的核心上,每个进程相互竞争。

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

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

或者选择一些其他的绑定(bind),这对于你运行的最终几何形状来说是有意义的。 MPICH 有 similar options with hydra .

请注意,子进程的 fork()ing 与 mpi isn't always safe or supported ,特别是对于使用 infiniband 互连运行的集群,但 OpenMPI 的 mpirun/mpiexec 会在不安全时警告您。

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

相关文章:

python - 解压缩通用数组的 numpy 数组形状

javascript - 有没有办法用一个按钮和唯一的隐藏值提交多个表单?

Python 在使用 multiprocessing.pool.map() 调用的函数中增加一个数字

python - Multiprocessing Pool 非阻塞检测完成的任务

c - MPI 进程数

C++和MPI如何并行编写部分代码?

c++ - 当接收方不发布接收时标准和非阻塞发送会发生什么

python - 使用 Pandas 在python中循环遍历多个excel文件

python method() 正好接受 1 个参数(给定 2 个)

multithreading - 如何在没有竞争条件的情况下在 Erlang 中按需启动 gen_server 或 gen_fsm?