我有一个使用multiprocessing模块编写的python脚本,以实现更快的执行速度。计算具有尴尬并行性,因此效率随处理器数量扩大而提高。现在,我想在管理多台计算机上的MCMC计算的MPI程序中使用它。该代码调用system(),以调用python脚本。但是,我发现当以这种方式调用时,使用python multiprocessing获取的效率优势消失了。
当从MPI调用时,该如何确保我的python脚本保留multiprocessing带来的速度提升?
以下是一个简单的示例,类似于我想要使用的更为复杂的代码,但显示出相同的一般行为。 我编写了一个名为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(),但它在我的计算机上已经工作了五年。例如,我曾在MPI程序中从system()调用基于pthread的并行代码,并且每个线程都使用了100%的CPU,正如所期望的那样。此外,如果您打算建议在串行模式下运行Python脚本并仅在更多节点上调用它,请注意MCMC计算涉及一定数量的需要同步移动的链,因此计算不能以这种方式重新组织。)
fork()
安全。如果该集群还使用大页,则可能需要“export RDMAV_HUGEPAGES_SAFE=1”。 - James Matta