python-3.x - 为什么在 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 分钟。
解决方案
多处理不是免费的。如果你有 X 个 cpu 核心,那么产生超过 X 个进程最终会导致性能下降。如果您的进程执行 I/O,那么即使生成 10*X 进程也可以。因为它们不会对 CPU 造成压力。但是,如果您的进程进行计算和内存操作,那么任何高于 X 的进程都可能只会降低性能。在评论中你说你有 4 个核心,所以你应该设置Pool(processes=4)
. 您也可以尝试不同的值。多处理很难,可能5个甚至8个进程仍然会提高性能。但极有可能 4 个 CPU 核心上的 24 个进程只会损害性能。
您可以做的另一件事是将数据批量发送到子流程。在您一一发送数据的那一刻,由于您的计算速度很快(对于单个数据点),可能是进程间通信支配了总执行时间。这是您在单进程方案中不支付的价格,但在多处理时您总是要付出代价。为了最小化它的影响,使用chunksize
的参数imap_unordered
。
最后,尝试重新实现您的算法以避免蛮力。正如@Alex 所建议的那样。
推荐阅读
- android - 如何使用 tabLayout 在 ViewPager 中显示片段?
- cocos2d-js - Cocos Creator 场景之间如何发送最终游戏分数?
- swiftui - 使用 ForEach 分层视图并使用 ZStack 偏移以创建一堆扑克筹码 (SwiftUI)
- html - Bootstrap - 在jumbotron上拥有一张卡片的最佳方式是什么?
- r - 使 igraph 图形在 Shiny App 中具有可移动节点的简单方法?
- laravel - search between 2 different dates with laravel
- android - 在 Android 上使用 DocuSign SDK 缓存模板需要多少可用空间?
- macos - terraform 手动安装插件失败
- regex - Combine two references into one or some serious regex work
- go - go get fails for hashicorp/levant