You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的代码并行版本比串行版本运行更慢?

并行化耗时更长的原因
  • 进程创建与上下文切换开销:手动创建Process实例时,每个进程的启动、内存拷贝(fork机制下)都有额外开销。当数据量不大时,这些开销会抵消甚至超过并行计算的收益;2核CPU下,进程间的上下文切换也会占用额外资源,拖慢整体速度。
  • 模型复用的潜在问题:主进程初始化的oracle模型在子进程中是fork继承的内存副本,这会导致内存占用翻倍,引发内存带宽竞争;若模型依赖底层状态(即使CPU运行),fork后的模型可能出现不稳定,进一步降低推理效率。
  • IO阻塞:子进程中频繁的print属于串行IO任务,多进程同时打印会导致控制台输出阻塞,额外增加耗时。
  • 结果收集错误:你用全局列表cr收集子进程结果,但fork后的子进程修改的是自身内存副本,主进程根本无法获取这些结果;这种无效的收集方式还会带来隐性内存管理开销。
优化方案
  1. 改用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)
    
  2. 移除不必要的IO操作
    删除子进程中的print语句,仅在主进程打印整体进度,避免多进程IO阻塞。

  3. 确保数据量适配并行场景
    若data长度过小(比如少于20条),并行的收益远不如进程开销,此时串行反而更快。只有当数据量达到数百条以上时,并行才能体现优势。

  4. 尝试多线程替代多进程
    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))
    
  5. 启用批量推理优化
    给pipeline添加batch_size参数,批量处理数据减少推理启动开销,配合并行使用效果更明显:

    # 串行/并行都可使用批量处理
    cr = oracle(question=question, context=data, batch_size=4)
    

内容的提问来源于stack exchange,提问作者Skapis9999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:21:02