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

Python multiprocessing.Process为何未充分利用全部CPU核心?

问题分析与解决思路

核心未充分利用的可能原因

1. Intel大小核架构的调度特性

你的i5-12600K是大小核混合架构:6个性能核(P-Core)+4个能效核(E-Core),超线程后显示16个逻辑核心。Windows调度器默认会把CPU密集型任务优先分配给P核,但如果你的任务存在启动开销小、优先级低等特性,系统可能反而将它们集中分配到E核上——而E核恰好是4个,这就会出现4个核心满负载、其余核心闲置的情况。

2. 子进程内部的多线程抢占

如果save_betas_over_window函数中用到了numpy、pandas这类依赖BLAS/LAPACK库的计算,这类库默认会启用多线程加速(比如MKL、OpenBLAS)。假设每个子进程启动后占用4个线程,4个子进程就会占满16个逻辑核心,但资源监视器显示的是物理核心负载,4个物理核满负载(每个核跑2个线程),其余物理核闲置,看起来就像只有4个核心在工作。

3. 任务计算量不均衡

你生成的windows列表是[30, 60, ..., 480],窗口越大,save_betas_over_window的计算量可能呈线性甚至非线性增长。窗口小的任务会很快执行完毕,对应的核心会闲置;只有窗口大的任务还在运行,导致后期只有少数核心处于高负载状态,看起来全程只有部分核心在工作。

4. Windows进程调度的随机性

虽然multiprocessing会启动指定数量的进程,但Windows调度器不会强制把进程均匀分配到所有核心上。如果调度器倾向于把多个进程放在同一组核心,就会出现部分核心过载、其余核心闲置的情况。


解决方法

1. 限制子进程内部的线程数

如果是BLAS库的多线程导致的问题,在代码开头添加环境变量设置,强制每个子进程只用1个线程:

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

这样每个子进程只会占用1个逻辑核心,16个进程就能均匀利用所有逻辑核心。

2. 调整进程数量为物理核心数

multiprocessing.cpu_count()返回的是逻辑核心数(16),但物理核心只有10个。试试把进程数量改成物理核心数,避免超线程带来的调度冲突:

from multiprocessing import cpu_count
import psutil

# 获取物理核心数
physical_cores = psutil.cpu_count(logical=False)
windows = np.linspace(30, physical_cores*30, physical_cores).astype(int)

3. 手动设置进程的CPU亲和性

使用psutil库手动把每个子进程绑定到不同的核心上,强制调度器分配资源:

import psutil

# ... 你的原有代码 ...
for idx, process in enumerate(processes):
    # 将进程绑定到第idx个逻辑核心
    psutil.Process(process.pid).cpu_affinity([idx])

4. 均衡任务计算量

如果是窗口大小导致的计算量不均衡,可以调整windows的生成方式,让每个任务的计算量尽量接近。比如采用对数间隔生成窗口,或者把大窗口拆分成多个小任务,避免部分进程长期占用核心。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:23:55