在Python中使用ProcessPool时出现意外的性能

时间:2018-10-10 11:45:40

标签: python concurrency

我正在尝试从Python使用ProcessPoolExecutor concurrent.futures软件包。但是,我的表现很差 我不明白为什么。

我的代码如下:

import time
from itertools import product
from concurrent.futures import ProcessPoolExecutor

def myfunc(bundle):
    "A simple function which takes some time to complete."
    clock_start = time.clock()
    for _ in range(*bundle):
        lst = [[0., 0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.95, 1.0]
                for x in range(6)]
        res = [t for t in product(*lst) if abs(sum(t) - 1.) < 1e-8]
    clock_elapsed = time.clock() - clock_start
    return clock_elapsed

def parallel(bundles, nworkers):
    "A function to dispatch execution between different workers."
    with ProcessPoolExecutor(max_workers=nworkers) as executor:
        execgen = executor.map(myfunc, bundles)
        total_clock = 0.
        for _clock in execgen:
            total_clock += _clock
    print("mean iteration: {:.3f} s".format(total_clock / bundles[-1][-1]))

(函数myfunc本身没有兴趣,但我希望 执行的迭代次数是线性的。

当我在计算机(Python 3.6,Debian,8 CPU)上测试此代码时,我 得到以下结果:

>>> parallel([(0, 60)], 1)
mean iteration: 3.660 s

>>> parallel([(0, 30), (30, 60)], 2)
mean iteration: 3.747 s

>>> parallel([(0, 20), (20, 40), (40, 60)], 3)
mean iteration: 4.413 s

>>> parallel([(0, 10), (10, 20), (20, 30), (30, 40), (40, 50), (50, 60)], 6)
mean iteration: 7.534 s

因此,显然,将执行分成6个工人意味着 一次迭代平均花费的时间是一次迭代的两倍 工人。由于迭代应该是完全独立的,所以我不能 弄清楚为什么会这样吗?

1 个答案:

答案 0 :(得分:0)

您的代码与您的动机不符。在您的代码的所有4次运行中,无论您使用多少个内核,total_clock始终是完成整个60个计算的 sum 时间。从理论上讲,所有4次运行都应返回相同的值,而不考虑多进程成本(通信...)。显然,这取决于实际的计算工作量,而不管它在哪个内核上运行。

我相信您想证明多进程就是时间效率。更新代码

print("mean iteration: {:.3f} s".format(total_clock / nworkers)) 

或者只是通过人类直觉来感觉和比较在这4次跑步返回之前经过的时间。