M1 Mac中multiprocessing.Pool无法利用全部核心的问题排查
问题:Python多进程池未充分利用CPU核心
我的代码如下:
from multiprocessing.dummy import Pool def process_board(elems): # 执行一些操作 for _ in range(1000): with Pool(cpu_count()) as p: _ = p.map(process_board, enumerate(some_array))
代码运行时Mac活动监视器截图:
我可以保证len(some_array) > 1000,理论上有足够多的任务分配,但实际CPU核心并未被充分利用。我忽略了什么?
更新:任务分块测试结果
我尝试对任务进行分块,测试不同分块大小的耗时:
# 每个分块的元素数 -> 耗时 # 100 -> 31.9秒 # 50 -> 31.8秒 # 20 -> 31.6秒 # 10 -> 32秒 # 5 -> 32秒
说明:我大约有1000个元素,每块100个元素对应10个分块,测试期间的CPU负载截图:
可以看到,更改分块数量后,仍无法利用剩余的4个CPU核心...
问题排查与解决
池类型错误:你用的
multiprocessing.dummy.Pool是线程池,受Python GIL(全局解释器锁)限制,同一时间仅能有一个线程执行Python代码,完全无法发挥多核CPU的优势。要实现真正的多核并行,必须改用multiprocessing.Pool(进程池)。频繁创建销毁池:循环内每次创建新
Pool会产生大量进程启停开销,挤占任务执行的CPU时间,导致核心利用率上不去。应该把池的初始化移到循环外部,复用进程资源。分块优化无效的原因:线程池下调整分块大小对多核利用没有帮助,只有换成进程池后,分块才会影响任务调度的开销,此时再根据实际情况调整分块大小才有意义。
修正后的代码
from multiprocessing import Pool, cpu_count def process_board(elems): # 执行你的业务操作 # 循环外创建进程池,复用进程资源 with Pool(cpu_count()) as p: for _ in range(1000): _ = p.map(process_board, enumerate(some_array))
额外提示
- 如果
process_board是IO密集型任务,线程池可以提升效率,但CPU密集型任务必须用进程池或concurrent.futures.ProcessPoolExecutor。 - 可尝试
p.imap_unordered或p.map_async替代p.map,减少任务等待时间,进一步提升核心利用率。
内容的提问来源于stack exchange,提问作者Alberto
相关产品推荐
相关产品推荐

