首页 > 解决方案 > 为什么在 Linux 上的 python 3 中,“多处理”版本比单进程版本花费更长的时间?

问题描述

我正在尝试将函数应用于大量range数字 - 我使用池的版本multiprocessing比我估计的“单进程”版本需要更长的时间来完成 -

这是我的代码有问题吗?还是蟒蛇?还是Linux?

我正在使用的功能is_solution定义如下-

as_ten_digit_string = lambda x: f"0000000000{x}"[-10:]

def sum_of_digits(nstr):
    return sum([int(_) for _ in list(nstr)])

def is_solution(x):
    return sum_of_digits(as_ten_digit_string(x)) == 10

当我运行is_solution一百万个数字时 - 大约需要 2 秒

In [13]: %timeit [is_solution(x) for x in range(1_000_000)]                                                                                                        
1.9 s ± 18.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

基于此——对于大约 100 亿个数字——它应该需要大约 20,000 秒或大约 6 小时。但该multiprocessing版本即使在 9 小时后也不会结束。

我正在使用这样的多处理模块 -

from multiprocessing import Pool
with Pool(processes=24) as p:
    for solution in p.imap_unordered(is_solution, range(1_000_000_000, 9_999_999_999)):
        if solution:
            print(solution)

我使用的python版本是3.8在linux上。

我不知道这是否相关——当我top在 linux 中运行命令时——我看到当我的主程序运行了约 200 分钟时——我的每个工作进程的 CPU 时间约为 20 分钟。

标签: python-3.xlinuxmultiprocessingpython-multiprocessing

解决方案


多处理不是免费的。如果你有 X 个 cpu 核心,那么产生超过 X 个进程最终会导致性能下降。如果您的进程执行 I/O,那么即使生成 10*X 进程也可以。因为它们不会对 CPU 造成压力。但是,如果您的进程进行计算和内存操作,那么任何高于 X 的进程都可能只会降低性能。在评论中你说你有 4 个核心,所以你应该设置Pool(processes=4). 您也可以尝试不同的值。多处理很难,可能5个甚至8个进程仍然会提高性能。但极有可能 4 个 CPU 核心上的 24 个进程只会损害性能。

您可以做的另一件事是将数据批量发送到子流程。在您一一发送数据的那一刻,由于您的计算速度很快(对于单个数据点),可能是进程间通信支配了总执行时间。这是您在单进程方案中不支付的价格,但在多处理时您总是要付出代价。为了最小化它的影响,使用chunksize的参数imap_unordered

最后,尝试重新实现您的算法以避免蛮力。正如@Alex 所建议的那样。


推荐阅读