【发布时间】:2020-04-06 08:21:06
【问题描述】:
我正在尝试将函数应用于大量的数字 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上。
我不知道这是否相关 - 当我在 linux 中运行 top 命令时 - 我看到当我的主程序运行约 200 分钟时 - 我的每个工作进程的 CPU 时间约为 20分钟。
【问题讨论】:
-
您只需生成所有数字之和 == 10 的数字的列表,您无需为此测试每个连续整数。
-
@Alex - 我很好奇如何。谢谢。但更重要的是,我希望了解我的代码为什么会这样运行——我不认为我的
is_solution函数是我看到的原因,或者是吗? -
如何让多处理代码运行?无论我尝试什么,我都会收到“无法腌制 lambda”错误。 mac 和 ubuntu,python 3.8。
-
@Mortz 你有多少核心?超过核心数量的每个进程都会降低性能。假设这些进程执行像您这样的 CPU 密集型任务。也可能是进程之间发送和接收数据的实际时间比实际处理时间长。要解决这个问题,您可以分批发送数据,而不是一个一个地发送。这意味着您可以将 [start, end] 对而不是单个值发送到
imap_unordered并修复您的is_solution以接受范围。 -
@Mortz 太好了,完美。只要记住将工作人员的数量保持在 cpus 的数量左右即可。 24 太多了。
标签: python-3.x linux multiprocessing python-multiprocessing