为何多进程未加速我的Python代码反而大幅变慢?
多进程未加速反而变慢的原因及优化方案
问题复现
用户测试多进程加速效果的代码如下:
from pathos.multiprocessing import Pool def wm(): l = [] for i in range(1000): for j in range(1000): l.append(i+j) return l def m(): with Pool() as pool: return pool.starmap(lambda x, y: x+y, ((i, j) for j in range(1000) for i in range(1000)))
通过%%timeit测试得到:
%%timeit wm() 79.1 ms ± 1.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit m() 11.8 s ± 5.12 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
结果显示多进程版本大幅慢于单进程,且运行时CPU占用率低。
原因分析
- 任务粒度过于精细:多进程版本将
1000*1000=100万个独立的x+y计算作为单个任务,每个任务的计算量极小,但进程间传递参数、返回结果的通信开销远大于计算本身的耗时。 - 进程切换开销:大量细粒度任务会导致频繁的进程上下文切换,进一步增加额外开销。
- CPU利用率低:大部分时间消耗在数据传输和进程调度上,实际用于计算的时间占比极低,因此CPU占用率上不去。
优化方案
核心思路是增大任务粒度,减少进程间通信的次数。将原本的百万个小任务合并为少数几个大任务,每个子进程处理一整块数据的循环计算:
from pathos.multiprocessing import Pool import os def process_chunk(start_i, end_i): l = [] for i in range(start_i, end_i): for j in range(1000): l.append(i+j) return l def optimized_m(): core_count = os.cpu_count() # 获取CPU核心数 chunk_size = 1000 // core_count # 按核心数拆分任务块 tasks = [] for i in range(0, 1000, chunk_size): tasks.append((i, min(i + chunk_size, 1000))) with Pool(core_count) as pool: results = pool.starmap(process_chunk, tasks) # 合并所有子进程的结果 final_list = [] for res in results: final_list.extend(res) return final_list
优化效果说明
优化后的代码将原本的百万个小任务拆分为与CPU核心数相等的大任务,每个子进程独立完成一块范围内的双层循环计算,仅在开始时传递任务的起止索引、结束时返回整块计算结果,大幅降低了进程间通信的开销,同时充分利用CPU资源,能有效实现加速。
内容的提问来源于stack exchange,提问作者TheRavenSpectre
相关产品推荐
相关产品推荐

