运行多个外部程序
因此,我设置了一个执行外部程序(用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个实例?
你可以使用一个线程池,让所有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()
。
虽然给定运行的执行时间可能会有很大差异,但通常假设例如用户所花的时间通常是安全的。连续运行10次的方差将少得多。
所以简单的解决方案A是启动8个进程,每次调用外部程序10次,然后等待这些进程完成。你仍然需要等待最慢的过程,但是开销会小得多。
当然,有一个显而易见的解决方案B:创建一个具有8个进程的未决运行池,一旦他们完成当前运行,将从池中选择一个新运行。这将真正减少过度头,但你必须在这里处理同步原语。
下面是这3种方法(使用一个和两个我说的)小图:
红色小方块表示在提升的空间是。基本上,方法A可以避免每个线程停止运行,而是每次运行一个线程。方法B变得更加进一步并且使已经完成其所有运行的线程从另一个线程取走一个线程。
我从另一张海报中得到了一个很好的解决方案,但是感谢这些想法/插图,我将在未来记住它。 –
你可以写一些看起来像。定义运行总数和可用内核数量,以及检查是否完成的延迟。对于延迟,只需将合理的秒数。如果一个过程平均在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!"
远比我的建议更短,更好 – innoSPG
哇多么干净的解决方案。我应该早些进入Python。谢谢! –