如何使用多处理程序包并行化python中的for循环?

时间:2019-04-15 20:04:30

标签: python-3.x python-multiprocessing python-multithreading

注意:我不需要进程/线程之间的任何通信,我只对完成信号感兴趣(这是我将所有其他示例都作为新问题发布的原因。已经发现彼此之间已进行通信)。

如何使用Python 3中的multiprocessing包并行化以下代码(最终目标是使其运行更快):

a = 123
b = 456
for id in ids: # len(ids) = 10'000
   # executes a binary with CLI flags
   run_binary_with_id(id, a, b) 
   # i.e. runs "./hello_world_exec --id id --a a --b b" which takes about 30 seconds on average

我尝试了以下操作:

import multiprocessing as mp

def run_binary_with_id(id, a, b):
    run_command('./hello_world_exec --id {} --a {} --b {}'.format(id, a, b))

if __name__ == '__main__':
    ctx = mp.get_context('spawn')
    q = ctx.Queue()
    a = 123
    b = 456
    ids = range(10000)
    for id in ids:
       p = ctx.Process(target=run_binary_with_id, args=(id,a,b))
       p.start()
    p.join()
    # The binary was executed len(ids) number of times, do other stuff assuming everything's completed at this point

for id in ids:
   map.apply_async(run_binary_with_id, (id,a,b))

similar question中,答案如下:

def consume(iterator):
    deque(iterator, max_len=0)
x=pool.imap_unordered(f,((i,j) for i in range(10000) for j in range(10000)))
consume(x)

我根本不了解(为什么需要这个consume())。

1 个答案:

答案 0 :(得分:1)

几乎可以肯定,尝试生成10000个进程以并行运行将使系统过载,并且使其运行速度比顺序运行进程慢,这是由于OS所涉及的开销,当操作系统数量不断增加时,该进程必须不断地在各个进程之间执行上下文切换。进程数远远超过了系统拥有的CPU /内核数。

您可以改为使用multiprocessing.Pool来限制为任务产生的辅助进程的数量。 Pool构造函数将进程数限制为系统默认具有的内核数,但是如果您愿意使用processes参数,则可以对其进行微调。然后,您可以使用其map方法来轻松映射一系列参数以应用于给定的函数以并行运行。但是,它只能将一个参数映射到函数,因此您将不得不使用functools.partial为其他参数提供默认值,在您的情况下,这些默认值在两次调用之间不会更改:

from functools import partial
if __name__ == '__main__':
    _run_binary_with_id = partial(run_binary_with_id, a=123, b=456)
    with mp.Pool() as pool:
        pool.map(_run_binary_with_id, range(10000))