繁体   English   中英

运行多个外部程序

[英]Running multiple external programs

因此,我设置了一个执行外部程序的短脚本(用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忙:

#!/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))

一个mej进程完成后,下一个进程就会启动。 只有os.cpu_count()并发工作进程一次运行。

虽然给定运行的执行时间可能显着不同,但通常可以安全地假设例如10次连续运行所花费的时间将具有更少的方差。

因此,简单的解决方案A是启动8个进程,每个进程调用外部程序10次,然后等待这些进程完成。 你仍然需要等待最慢的过程,但开销会相当小。

当然有一个明显的解决方案B :创建一个暂挂运行池,其中8个进程在完成当前运行后从池中选择一个新运行。 这将真正最小化ovehead,但你必须在这里处理同步原语。

以下是这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!"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM