如何在多处理器系统上生成并行子进程?

tat*_*lar 42 python subprocess exec multiprocessing

我有一个Python脚本,我想用作另一个Python脚本的控制器.我有一个64位处理器的服务器,所以想要产生第二个Python脚本的64个子进程.子脚本被调用:

$ python create_graphs.py --name=NAME
Run Code Online (Sandbox Code Playgroud)

其中NAME是XYZ,ABC,NYU等.

在我的父控制器脚本中,我从列表中检索名称变量:

my_list = [ 'XYZ', 'ABC', 'NYU' ]
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,作为孩子产生这些过程的最佳方法是什么?我想一次将子项数限制为64,因此需要跟踪状态(如果子进程已完成或未完成),这样我就可以有效地保持整个代的运行.

我查看了使用子进程包,但拒绝它,因为它一次只生成一个子进程.我终于找到了多处理器包,但我承认被整个线程与子进程文档所淹没.

现在,我的脚本subprocess.call一次只生成一个孩子,看起来像这样:

#!/path/to/python
import subprocess, multiprocessing, Queue
from multiprocessing import Process

my_list = [ 'XYZ', 'ABC', 'NYU' ]

if __name__ == '__main__':
    processors = multiprocessing.cpu_count()

    for i in range(len(my_list)):
        if( i < processors ):
             cmd = ["python", "/path/to/create_graphs.py", "--name="+ my_list[i]]
             child = subprocess.call( cmd, shell=False )
Run Code Online (Sandbox Code Playgroud)

我真的希望它一次产生64个孩子.在其他stackoverflow问题中,我看到人们使用Queue,但似乎这会产生性能损失?

Nad*_*mli 61

您正在寻找的是多处理中的进程池类.

import multiprocessing
import subprocess

def work(cmd):
    return subprocess.call(cmd, shell=False)

if __name__ == '__main__':
    count = multiprocessing.cpu_count()
    pool = multiprocessing.Pool(processes=count)
    print pool.map(work, ['ls'] * count)
Run Code Online (Sandbox Code Playgroud)

这是一个计算示例,使其更容易理解.以下将在N个进程上划分10000个任务,其中N是cpu计数.请注意,我正在传递None作为进程数.这将导致Pool类使用cpu_count进行进程数(引用)

import multiprocessing
import subprocess

def calculate(value):
    return value * 10

if __name__ == '__main__':
    pool = multiprocessing.Pool(None)
    tasks = range(10000)
    results = []
    r = pool.map_async(calculate, tasks, callback=results.append)
    r.wait() # Wait on the results
    print results
Run Code Online (Sandbox Code Playgroud)