0

我有一个 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]
    ...

无论如何,关于问题的原因。我将此脚本提交给网格引擎系统,以将这个巨大的参数空间扫描分解为 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,这似乎不会改变事情。

4

0 回答 0