与ProcessPpplExecutor相比,为什么Python ThreadPoolExecutor.map需要很长时间才能开始产生结果?

时间:2017-03-01 14:59:52

标签: python generator python-multithreading

采用这个示例程序:

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

def fun(xx):
    for _ in range(10):
        y = 1
        x = xx
        while x > 0:
            y = (y * x) % 1000000007
            x -= 1
    print("END {}! = {}".format(xx, y))
    return xx, y

with ThreadPoolExecutor(max_workers=8) as executor:
    out = executor.map(fun, range(10000))
    for x in out:
        print(x)

这让我可以看到每次实际计算函数时打印的消息,以及从输出生成器中读取输出时的消息。人们应该期望功能消息不是严格按顺序排列,而生成器是。此外,我希望生成器为我提供“作为管道”的数据,在处理整个输入之前给出中间结果。这可能是我正在处理的无限流。

如果我使用ProcessPoolExecutor,这就像我预期的那样工作,我很快就可以在线程池创建新结果时从输出生成器开始读取。另一方面,使用ThreadPoolExecutor,虽然它似乎工作正常,但它只在很多函数执行已经发生后才开始向我提供输出。例如:

END 6363! = 280520285
END 6364! = 231081245
END 6365! = 832114135
END 6366! = 238546331
(0, 1)
(1, 1)
(2, 2)
(3, 6)
(4, 24)
END 6368! = 281286418
END 6369! = 513183705
END 6370! = 980177974

为什么会有这么大的差异,我该如何控制这种行为?如果我想使用线程,并且我想确保我的结果更快,我应该自己分块数据而不是依赖map吗?

1 个答案:

答案 0 :(得分:0)

你在ProcessPoolExecutor中获得更快结果的一个原因是它产生了一大块迭代器,因此每个块都会进入cpu的核心(你指定的worker的数量),并且该核心可能会更快地完成其块的计算,并且它可以更进一步并执行你的for循环