2015-07-21 70 views
2

因此,我設置了一個執行外部程序(用Fortran 77編寫)的簡短腳本。我要運行的程序的多個實例,因爲我有我的電腦上8個核心,我發現最簡單的解決辦法是:運行多個外部程序

import subprocess 


import os 


i = n 

while(i<n): 
    dire = "dir/Run"+str(i)+"/" 
    os.chdir(dire) 
    p1 = subprocess.Popen(['./mej']) 
    dire = "dir/Run"+str(i+1)+"/" 
    os.chdir(dire) 
    p2 = subprocess.Popen(['./mej']) 
    dire = "dir/Run"+str(i+2)+"/" 
    os.chdir(dire) 
    p3 = subprocess.Popen(['./mej']) 
    dire = "dir/Run"+str(i+3)+"/" 
    os.chdir(dire) 
    p4 = subprocess.Popen(['./mej']) 
    dire = "dir/Run"+str(i+4)+"/" 
    os.chdir(dire) 
    p5 = subprocess.Popen(['./mej']) 
    dire = "dir/Run"+str(i+5)+"/" 
    os.chdir(dire) 
    p6 = subprocess.Popen(['./mej']) 
    dire = "dir/Run"+str(i+6)+"/" 
    os.chdir(dire) 
    p7 = subprocess.Popen(['./mej']) 
    dire = "dir/Run"+str(i+7)+"/" 
    os.chdir(dire) 
    p8 = subprocess.Popen(['./mej']) 
    dire = "/Run"+str(i+8)+"/" 
    os.chdir(dire) 
    p3 = subprocess.Popen(['./mej']) 
    exit_codes = [p.wait() for p in p1, p2, p3, p4, p5, p6, p7, p8] 
    i = i + 8 



print "Job's done!" 

現在這個工作在第一大多正常,但是我只是改變一個變量的時間步長和在這樣做時,每次集成運行的時間差別很大。現在問題是腳本會在啓動一套新的集成之前等待最慢的腳本完成。我如何編寫它,以便始終運行8個實例?

回答

1

你可以使用一個線程池,讓所有CPU忙道:作爲一個mej過程完成後儘快

#!/usr/bin/env python 
import os 
import subprocess 
from multiprocessing.pool import ThreadPool 

def run(i): 
    working_dir = "dir/Run/" + str(i + 1) 
    return i, subprocess.call(os.path.join(working_dir, 'mej'), cwd=working_dir) 

results = ThreadPool().map(run, range(n)) 

,下一個開始。同時運行的併發工作進程不超過os.cpu_count()

+0

遠比我的建議更短,更好 – innoSPG

+0

哇多麼乾淨的解決方案。我應該早些進入Python。謝謝! –

0

雖然給定運行的執行時間可能會有很大差異,但通常假設例如用戶所花的時間通常是安全的。連續運行10次的方差將少得多。

所以簡單的解決方案A是啓動8個進程,每次調用外部程序10次,然後等待這些進程完成。你仍然需要等待最慢的過程,但是開銷會小得多。

當然,有一個顯而易見的解決方案B:創建一個具有8個進程的未決運行池,一旦他們完成當前運行,將從池中選擇一個新運行。這將真正減少過度頭,但你必須在這裏處理同步原語。

下面是這3種方法(使用一個和兩個我說的)小圖:

enter image description here

紅色小方塊表示在提升的空間是。基本上,方法A可以避免每個線程停止運行,而是每次運行一個線程。方法B變得更加進一步並且使已經完成其所有運行的線程從另一個線程取走一個線程。

+1

我從另一張海報中得到了一個很好的解決方案,但是感謝這些想法/插圖,我將在未來記住它。 –

0

你可以寫一些看起來像。定義運行總數和可用內核數量,以及檢查是否完成的延遲。對於延遲,只需將合理的秒數。如果一個過程平均在10分鐘內運行,60秒或更少的延遲就足夠了。

import subprocess 
import time 
import os 

def runIt(rootDir, prog, i): 
    dire = "dir/Run/" + str(i + 1) 
    os.chdir(dire) 
    return subprocess.Popen(['./mej']) 

n=16 #total number of runs 
nProc = 8 # number of cores 
i = 0 
delay = 2 #delays in second to check if one has returned 

pList = [runIt(p) for p in range(min(nProc, n))] 
i = len(pList) 
while(i<n): 
    time.sleep(delay) # delays for delay seconds 
    for j in range(len(pList)): 
     pList[j].poll() 
     if pList[j].returncode is not None and i<n: 
      pList[j] = runIt(i) 
      i = i+1 
print "Job's done!"