Python多进程Queue/Pool性能不及普通循环问题排查
问题分析与优化方案
你的代码存在几个关键问题,导致多进程版本反而比单进程慢:
1. Queue版本:本质是单进程,额外增加开销
你只创建了一个Process来消费队列,相当于把单进程的任务拆成队列分发,但实际还是一个进程在执行所有任务,还多了队列的通信开销,自然比普通循环慢。
2. Pool版本:函数效率低+随机模块全局锁拖慢速度
(1)run_sims函数内存开销过大
每次生成3000万个元素存入列表再求和,会占用大量内存(每个float占8字节,3000万次就是240MB/任务)。多进程同时运行时,内存占用翻倍甚至更多,容易触发系统内存交换(swap),大幅拖慢速度。
(2)random模块的全局锁限制并行
Python标准库的random模块底层使用共享全局状态,多进程同时调用random.uniform时会触发全局锁,导致进程互相等待,抵消了多进程的并行优势。
优化后的代码
第一步:优化run_sims函数
去掉不必要的列表存储,直接累加数值;每个进程初始化独立的随机生成器,避免全局锁:
import time from multiprocessing import Process, Queue, Pool import random import os def run_sims(iterations): total = 0.0 # 每个进程初始化独立的随机生成器,规避全局锁 rng = random.Random() for _ in range(iterations): total += rng.uniform(0, 1) avg = total / iterations print(iterations, "count", avg) return avg def worker(queue): while not queue.empty(): task = queue.get() run_sims(task) if __name__ == '__main__': iterations_list = [30000000, 30000000, 30000000, 30000000, 30000000] it_len = len(iterations_list) ## 优化后的Queue版本:多进程消费队列 print("#STARTING QUEUE#") start_t = time.perf_counter() queue = Queue() for it in iterations_list: queue.put(it) # 根据CPU核心数创建进程,充分利用硬件资源 num_processes = os.cpu_count() processes = [] for _ in range(num_processes): p = Process(target=worker, args=(queue,)) p.start() processes.append(p) for p in processes: p.join() end_t = time.perf_counter() print("Queue time: ", end_t - start_t) ## 优化后的Pool版本 print("#STARTING POOL#") start_t = time.perf_counter() with Pool() as pool: # 用map替代imap_unordered,减少迭代过程的额外开销 results = pool.map(run_sims, iterations_list) end_t = time.perf_counter() print("Pool time: ", end_t - start_t) ## 普通循环 print("#STARTING NORMAL LOOP#") start_t = time.perf_counter() for i in iterations_list: run_sims(i) end_t = time.perf_counter() print("Normal time: ", end_t - start_t)
优化效果说明
- 优化后的
run_sims函数内存占用从240MB/次降到几乎可忽略,避免了内存交换导致的性能下降。 - 独立的随机生成器消除了全局锁,让多进程真正实现并行计算。
- Queue版本改为多进程消费,充分利用CPU核心资源。
- Pool版本用
map替代imap_unordered,减少了迭代过程的额外开销。
内容的提问来源于stack exchange,提问作者pdon
相关产品推荐
相关产品推荐

