我的Python多进程程序按顺序运行工作程序

4

我已经写了一个使用多进程的Python程序。该程序调用8个工作进程,在睡眠3秒后输出一个随机数。我期望程序在3秒内完成,但实际上需要24秒才能完成,就好像每个工作进程函数是按顺序而不是并行评估的。有什么想法吗?

import time
import numpy as np
import multiprocessing as mp
import time
import sys

def f(i):
    np.random.seed(int(time.time()+i))

    time.sleep(3)
    res=np.random.rand()
    print "From i = ",i, "       res = ",res


if __name__=='__main__':
    num_workers=mp.cpu_count()     # My CPu has 8 cores. 
    pool=mp.Pool(num_workers)  
    for i in range(num_workers):
        p=pool.apply_async(f, args=(i,))
        p.get()

    pool.close()        
    pool.join()

然而,如果我使用Process而不是Pool,我会得到预期的正确结果:
import time
import numpy as np
import multiprocessing as mp
import time
import sys

def f(i):
    np.random.seed(int(time.time()+i))

    time.sleep(3)
    res=np.random.rand()
    print "From i = ",i, "       res = ",res
    if res>0.7:
        print "find it"


if __name__=='__main__':
    num_workers=mp.cpu_count()
    pool=mp.Pool(num_workers)
    for i in range(num_workers):
        p=mp.Process(target=f,args=(i,))
        p.start()
1个回答

8

想一想你在做什么:

for i in range(num_workers):
    p=pool.apply_async(f, args=(i,))
    p.get()

在循环中,每次您都会将一些工作发送到池进程,然后(通过.get())您会显式地等待该进程返回其结果。因此,几乎没有并行执行的效果。
通常的做法更像是:
workers = [pool.apply_async(f, args=(i,)) for i in range(num_workers)]
for w in workers:
    w.get()

也就是说,在等待任何一个工人之前,您可以启动所需数量的工作进程。

1
你也可以使用 pool.map(f, range(num_workers)),它会为你收集结果。 - Blckknght
@Blckknght,当然 - 我假设OP的问题是他们真正想要做的事情的一个巨大简化,并且在他们真正的应用程序中,apply_async()map()更有意义。 但是,我当然不知道那个;-) - Tim Peters
四年后来到这里,你的评论救了我的一天!@TimPeters - ekosman
谢谢您,我也一直在想为什么我的进程是顺序/线性的,这让我清楚了! - Vaidøtas I.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接