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

Python multiprocessing多进程代码运行速度远慢于单线程问题求解

问题原因分析
  • 错误使用同步阻塞的pool.apply()接口
    pool.apply()是同步执行方法,每次调用都会阻塞主进程,等待对应任务执行完成返回结果后才会继续执行后续代码。你在循环中调用1000万次apply(),本质还是串行执行所有任务,没有任何并行效果,反而每次调用都要额外付出进程调度、跨进程数据传输的开销,所以速度远低于纯串行实现。
  • 任务粒度过小,额外开销远超计算收益
    你设定的每个任务仅处理长度为5的一行数组,单次任务的计算量极小。而Python多进程受GIL限制,跨进程传递参数、返回结果都需要做序列化/反序列化操作,1000万次任务的额外开销总和已经远远超过了并行计算能带来的收益,自然会出现越改越慢的情况。
优化方案
  1. 替换任务提交接口,使用pool.starmap()批量提交任务,避免循环单次提交的调度开销;如果需要异步执行可以选择starmap_async()。
  2. 调整任务粒度,把大数组拆分为和CPU核心数相近的大块,每个进程处理一个大块,大幅降低跨进程通信的占比。
  3. 优先使用numpy向量化操作替代Python循环,numpy内置运算本身已经做了底层优化,哪怕串行执行速度也远快于手写Python循环,小计算量场景下不需要引入多进程就能满足性能需求。

优化后的多进程实现示例

import time
import multiprocessing as mp
import numpy as np

def how_many_within_range(chunk, minimum, maximum):
    # 直接用numpy向量化计算,替代循环
    return np.sum((chunk >= minimum) & (chunk <= maximum), axis=1)

if __name__ == '__main__':
    data = np.random.randint(0, 10, size=[10000000, 5])
    print(data[:5])

    start_time = time.perf_counter()

    # 拆分数组为和CPU核心数相同的块
    cpu_count = mp.cpu_count()
    chunks = np.array_split(data, cpu_count)

    with mp.Pool(cpu_count) as pool:
        # 批量提交任务,每个任务处理一个大块
        results = pool.starmap(how_many_within_range, [(chunk, 4, 8) for chunk in chunks])
    
    # 合并结果
    results = np.concatenate(results)

    print(f'Time elapsed: {time.perf_counter() - start_time}')
    print(results[:5])

如果你不需要多进程,直接用向量化的numpy运算,速度会更快:

start_time = time.perf_counter()
results = np.sum((data >=4) & (data <=8), axis=1)
print(f'Time elapsed: {time.perf_counter() - start_time}')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:09:03