2014-09-10 88 views
11

我有一個使用多處理模塊編寫的python腳本,以加快執行速度。計算結果令人尷尬並行,所以效率隨着處理器數量而變化。現在,我想在一個MPI程序中使用它,該程序管理多臺計算機上的MCMC計算。這段代碼調用了調用python腳本的system()。然而,我發現,當它被這樣調用時,使用python多處理的效率增益消失了。mpi內的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中運行這個,使用「頂級」我可以看到三個蟒蛇的過程我的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,每個蟒蛇過程需要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,2.7.3蟒蛇Linux上的Debian版喘息我聽到系統()不總是被允許MPI程序中,但它已經爲我工作了。例如,我在MPI程序中調用了system()中基於pthread的並行代碼,並且根據需要使用每個線程的100%cpu。另外,如果您打算建議以串行方式運行python腳本並在更多節點上調用它... MCMC計算包括需要以同步方式移動的固定數量的鏈,因此不幸的是計算不能以這種方式進行重組。)

回答

8

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

請注意,具有mpi isn't always safe or supported的子進程fork(),尤其是使用infiniband互連運行的羣集,但OpenMPI的mpirun/mpiexec會警告您是否安全。

+0

所以答案是關閉腳本中的多處理? – Cmag 2014-09-10 18:43:10

+1

對不起,哪個部分的答案?使用--bind-to none啓動將避免CPU問題。至於叉問題,OpenMPI的mpirun/mpiexec會讓你知道你是否在fork不安全的情況下運行,並且你可以在出現問題時解決這個問題。 – 2014-09-10 18:45:15

+0

我已經證實這個解決方案的工作原理,既有簡單的例子,也有我真實的代碼。非常感謝!我猜測mpirun的這種行爲隨着openmpi 1.7版本中的綁定選項而改變,否則我不明白爲什麼我之前運行的某些代碼會起作用。 – 2014-09-11 14:59:17