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

Python multiprocessing Pool.map指定进程却占用全部核心问题

多进程Pool指定8进程但双CPU机器出现大量进程的问题分析

核心问题现象

在单12核机器上使用multiprocessing.Pool(processes=8)时,htop显示8个目标进程,符合预期;但在双20核(共40核)机器上,即使指定8个进程,htop却显示数百个python EA_launch.py条目,占满所有40核,导致性能骤降。

可能原因及分析

  • evaluate函数内部触发了额外并行
    检查evaluate函数是否在内部调用了多进程/多线程逻辑,或是使用了默认自动并行的第三方库(如numpy的BLAS后端、pandas的某些操作、机器学习框架)。这类库通常会根据机器核心数自动分配资源,当Pool的8个进程各自都启动全核心并行时,总线程/进程数会达到8×40=320,远超机器承载能力,引发大量上下文切换,拖慢整体速度。

  • 进程启动方式导致的资源继承问题
    Unix系统下multiprocessing默认用fork方式启动子进程,若主进程在创建Pool前已初始化了线程池、全局状态等资源,子进程会继承这些资源,进而触发意外的并行逻辑。单CPU机器核心数少,这类副作用表现不明显;双CPU机器核心充足,问题会被放大。

  • htop显示的是线程而非进程
    htop默认会显示线程(按H键可切换进程/线程视图),如果evaluate内部使用多线程,htop会把每个线程当作独立条目展示,看起来进程数远超8个,但实际是线程。双CPU核心多,线程拉满后会占满所有核心,导致CPU调度效率急剧下降。

验证与解决方法

  1. 确认进程/线程数量
    在evaluate函数开头加入print(os.getpid()),运行后统计输出的PID数量:

    import os
    def evaluate(obj):
        print(f"当前进程ID: {os.getpid()}")
        # 业务逻辑
        ...
    
    • 若PID数量为8,说明是线程导致的htop显示“进程数过多”;若PID远超8,则是evaluate内部创建了额外进程。
  2. 限制子进程的并行资源
    针对自动并行的第三方库,在evaluate内部设置环境变量限制核心数:

    def evaluate(obj):
        import os
        # 限制OpenBLAS/MKL使用1核心
        os.environ['OPENBLAS_NUM_THREADS'] = '1'
        os.environ['MKL_NUM_THREADS'] = '1'
        # 业务逻辑
        ...
    
  3. 更换进程启动方式
    使用spawn方式创建Pool,避免继承主进程的线程或全局资源:

    import multiprocessing as mp
    
    if __name__ == '__main__':
        mp.set_start_method('spawn')
        pool = mp.Pool(processes=8)
        pool.map(evaluate, object_list)
    
  4. 调整htop显示设置
    按H键切换到进程视图,确认实际进程数量是否为8,区分进程与线程的显示差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:08:27