为何我的代码并行版本比串行版本运行更慢?
并行化耗时更长的原因
- 进程创建与上下文切换开销:手动创建
Process实例时,每个进程的启动、内存拷贝(fork机制下)都有额外开销。当数据量不大时,这些开销会抵消甚至超过并行计算的收益;2核CPU下,进程间的上下文切换也会占用额外资源,拖慢整体速度。 - 模型复用的潜在问题:主进程初始化的
oracle模型在子进程中是fork继承的内存副本,这会导致内存占用翻倍,引发内存带宽竞争;若模型依赖底层状态(即使CPU运行),fork后的模型可能出现不稳定,进一步降低推理效率。 - IO阻塞:子进程中频繁的
print属于串行IO任务,多进程同时打印会导致控制台输出阻塞,额外增加耗时。 - 结果收集错误:你用全局列表
cr收集子进程结果,但fork后的子进程修改的是自身内存副本,主进程根本无法获取这些结果;这种无效的收集方式还会带来隐性内存管理开销。
优化方案
改用
multiprocessing.Pool复用进程
Pool会预先创建进程池,避免重复创建进程的开销,同时内置高效的结果收集机制。示例代码:from multiprocessing import Pool def process_single_item(context): return oracle(question=question, context=context) if parallel == True: no_CPU = multiprocessing.cpu_count() # 若模型继承有问题,用初始化函数在子进程内加载模型 def init_worker(): global oracle oracle = pipeline(model="deepset/roberta-base-squad2") with Pool(no_CPU, initializer=init_worker) as pool: cr = pool.map(process_single_item, data)移除不必要的IO操作
删除子进程中的print语句,仅在主进程打印整体进度,避免多进程IO阻塞。确保数据量适配并行场景
若data长度过小(比如少于20条),并行的收益远不如进程开销,此时串行反而更快。只有当数据量达到数百条以上时,并行才能体现优势。尝试多线程替代多进程
transformers推理底层会调用释放GIL的库(如PyTorch CPU推理、numpy),多线程也能利用多核CPU,且避免进程创建开销。示例:from concurrent.futures import ThreadPoolExecutor if parallel == True: with ThreadPoolExecutor(max_workers=no_CPU) as executor: cr = list(executor.map(process_single_item, data))启用批量推理优化
给pipeline添加batch_size参数,批量处理数据减少推理启动开销,配合并行使用效果更明显:# 串行/并行都可使用批量处理 cr = oracle(question=question, context=data, batch_size=4)
内容的提问来源于stack exchange,提问作者Skapis9999
相关产品推荐
相关产品推荐

