减少Python Subprocess的系统时间使用

时间:2013-10-09 21:19:04

标签: python subprocess multiprocessing grid-computing

我有一个python脚本,它使用多处理的pool.map(...)来并行运行大量计算。这些计算中的每一个都包含为fortran程序设置输入的python脚本,使用subprocess.popen(...,stdin = PIPE,stdout = PIPE,stderr = PIPE)来运行程序,将输入转储给它并读取输出。然后脚本解析输出,获取所需的数字,然后再次进行下一次运行。

def main():
    #Read a configuration file
    #do initial setup
    pool = multiprocessing.Pool(processes=maxProc)
    runner = CalcRunner( things that are the same for each run )
    runNumsAndChis = pool.map( runner, xrange(startRunNum, endRunNum))
    #dump the data that makes it past a cut to disk

class CalcRunner(object):
    def __init__(self, stuff):
        #setup member variables
    def __call__(self, runNumber):
        #get parameters for this run
        params = self.getParams(runNum)
        inFileLines = []
        #write the lines of the new input file to a list
        makeInputFile(inFileLines, ... )
        process = subprocess.Popen(cmdString, bufsize=0, stdin=subprocess.PIPE, ... )
        output = proc.communicate( "".join(inFileLines) )
        #get the needed numbers from stdout
        chi2 = getChiSq(output[0])
        return [runNumber, chi2]
    ...

无论如何,关于问题的原因。我将这个脚本提交给一个Grid Engine系统来打破这个巨大的参数空间扫描到1000,12核心(我选择了12个,因为大部分网格是12个核心),任务。当单个任务在单个12核计算机上运行时,大约1/3的机器时间用于执行系统操作,而另外2/3的时间正在进行用户计算,可能是为ECIS设置输入(前面提到的FORTRAN)代码),运行ECIS,并解析ECIS的输出。但是,有时会将5个任务发送到64核计算机以使用其60个核心。在那台机器上,40%的时间花在做系统事情上,1-2%用于做用户事。

首先,所有系统调用来自哪里?我尝试编写一个程序版本,每个单独的线程运行ECIS一次,并保持管道新输入,它在系统中花费更多的时间(总体上更慢),所以它似乎不是由于所有的流程创建和删除。 其次,我该如何减少花在系统调用上的时间?

猜测,打开一个进程并继续向它发送输入的速度较慢,因为我不得不关闭gfortran的输出缓冲以从进程中获取任何内容,没有其他工作(没有修改fortran代码...没有发生。)

我开发的家用测试机上的操作系统是Fedora 14.网格机上的操作系统是Red Hat的最新版本。

我尝试过使用bufsize,将其设置为-1(系统默认值),0(无缓冲),1(逐行)和64Kb似乎不会改变。

0 个答案:

没有答案