Python双函数多参数并行执行实现方案:单/多进程池优劣对比
方案对比与最优实现说明
单Pool方案测试性能差的核心原因
你写的单Pool代码存在两处使用错误,才导致任务看起来串行、耗时更长:
- 连续调用两次
map_async时,第一批提交的10个func_a任务直接占满了大小为8的进程池,剩余排队的func_a任务优先级高于后提交的func_b任务,所以func_b的所有任务要等func_a全部执行完才会启动,并没有实现两类任务并行。 - 你没有保留第一个
map_async的返回句柄,也没有显式调用get()等待两类任务的执行结果,虽然join()会等待所有任务完成,但调度逻辑没有优化空间。
两种方案的公认优先级对比
- 优先选择单进程池方案:这是符合最佳实践的做法,进程池的设计初衷就是复用进程资源,避免重复创建销毁进程的开销,单池的全局调度也能更合理地利用CPU资源,不会出现进程数随业务逻辑线性增长的问题,后续维护、扩展成本更低。
- 双进程+双Pool方案仅适合特殊场景:只有当你需要对两类任务做资源强隔离(比如某类任务优先级极高,不允许被另一类抢占进程资源)时才考虑使用,否则额外的进程管理开销、资源碎片化问题会在CPU密集型场景下导致性能明显下降,你测试时因为是sleep类的IO密集型任务,才没有暴露这个问题。
更优的单Pool实现方案
要实现两类任务在单池内并行,可以调整提交逻辑,让两类任务交错进入进程池调度队列,修正后的代码如下:
from multiprocessing import Pool import time import os data = list(range(1, 11)) def func_a(param): print(f'running func_a in process {os.getpid()}') print(f'passed argument: {param}') print('calculating...\n') time.sleep(1.5) print('done\n') return ('a', param) def func_b(param): print(f'running func_b in process {os.getpid()}') print(f'passed argument: {param}') print('calculating...\n') time.sleep(2.5) print('done\n') return ('b', param) if __name__ == '__main__': t0 = time.time() with Pool(processes=8) as p: # 逐个提交两类任务,让队列交错排布 tasks = [] for param in data: tasks.append(p.apply_async(func_a, args=(param,))) tasks.append(p.apply_async(func_b, args=(param,))) # 等待所有任务完成 results = [task.get() for task in tasks] t1 = time.time() dt = t1 - t0 print(f'time spent with optimized one pool: {dt} s')
修正后两类任务会并行调度,总耗时和你用双Pool的测试结果基本一致,甚至在CPU密集场景下性能更好,同时还保留了单池易管理、资源利用率高的优势。
内容的提问来源于stack exchange,提问作者Andre
相关产品推荐
相关产品推荐

