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

Multiprocessing.Pool指定4进程却占用全部CPU的解决问询

限制Stable Baselines3多进程场景下的CPU占用问题

问题描述

在40核的共享Ubuntu 20.04服务器上运行540个强化学习实验,为避免占用全部资源,使用multiprocessing.Pool(processes=4)控制同时运行的进程数,但通过htop观察发现所有40核均被占满,每个子进程占用大量CPU核心。尝试调整chunksize参数及map/map_async等Pool方法后,问题未解决。

使用的核心代码如下:

from stable_baselines3.common.callbacks import EvalCallback
from stable_baselines3.common.logger import configure
from stable_baselines3 import PPO
from vrpEnv import VRPEnv
import multiprocessing
import time  # 原代码遗漏time模块导入

expList = [*range(1, 541)]

ITERATIONS = 500
TIMESTEPS = 2048*10

def runExperiment(exp):
    models_dir = "models/" + str(exp)  # 原代码exp为整数,需转字符串避免报错
    log_dir = "logs/"

    rank = multiprocessing.current_process()._identity[0]
    print(f"Processor {rank} working on case {exp}")

    env = VRPEnv()

    model = PPO("MultiInputPolicy", env, verbose=1, tensorboard_log=log_dir, device='cpu')
   
    eval_callback = EvalCallback(env, best_model_save_path=models_dir,
                            eval_freq=40000, deterministic=True, render=False)

    new_logger = configure(log_dir, format_strings = ["log", "csv", "tensorboard"])  # 原代码缺少log_dir参数
    nombreExp = f"exp_{exp}"  # 原代码未定义nombreExp变量

    start_time = time.time()

    for _ in range(1, ITERATIONS+1):
        model.set_logger(new_logger)
        model.learn(total_timesteps = TIMESTEPS, reset_num_timesteps = False, tb_log_name = nombreExp, callback=eval_callback)

    print("---%s: %s minutos ---" % (exp, round((time.time() - start_time)/60, 2)))

    env.close()

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes = 4)
    result = pool.imap(runExperiment, expList)
    pool.close()
    pool.join()
    print('END')

问题原因

multiprocessing.Pool(processes=4)仅限制了同时运行的进程数,但Stable Baselines3的PPO模型默认会启用内部多线程加速(依赖PyTorch、NumPy等库的并行计算能力),每个子进程会自动占用多个CPU核心,最终导致所有40核被占满。

解决方案

1. 限制PyTorch线程数

在每个子进程的初始化阶段,强制PyTorch仅使用1个线程,避免单个进程占用多核心。在runExperiment函数开头添加:

import torch
torch.set_num_threads(1)
torch.set_num_interop_threads(1)

2. 限制OpenMP相关库的线程数

NumPy、MKL等依赖OpenMP的库也会自动启用多线程,需通过环境变量限制其线程数。可以在代码开头全局设置:

import os
os.environ["OMP_NUM_THREADS"] = "1"
os.environ["MKL_NUM_THREADS"] = "1"
os.environ["NUMEXPR_NUM_THREADS"] = "1"

或者在终端启动脚本时直接设置环境变量:

OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 NUMEXPR_NUM_THREADS=1 python your_script.py

3. 修正原代码中的潜在问题

原代码存在几处语法/逻辑错误,需修正后才能正常运行:

  • 遗漏time模块导入
  • models_dir = "models/" + exp中exp是整数,需转为字符串
  • configure函数缺少log_dir参数
  • 未定义nombreExp变量

验证效果

应用上述设置后,每个子进程仅会占用1个CPU核心,4个并行进程最多占用4核,不会再出现全核心占用的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:28:16