如何让Python multiprocessing Pool充分利用双CPU节点全部核心?
解决Windows下NUMA节点CPU利用率不均的问题
你的问题核心是Python的multiprocessing默认继承父进程的CPU亲和性,父进程大概率被绑定在了NUMA节点1的核心上,导致所有子进程都只在节点1运行,节点2闲置。以下是具体解决方法:
方法1:用psutil手动设置进程CPU亲和性
通过psutil库可以灵活控制每个子进程的核心绑定,将任务平均分配到两个NUMA节点:
首先安装依赖:
pip install psutil
修改代码如下:
from multiprocessing import Pool import psutil import os # 获取两个NUMA节点的核心列表(假设节点1是0-47,节点2是48-95,可根据实际硬件调整) numa_node1_cores = list(range(48)) numa_node2_cores = list(range(48, 96)) def init_worker(worker_idx): # 给每个子进程分配对应节点的核心 pid = os.getpid() process = psutil.Process(pid) if worker_idx % 2 == 0: process.cpu_affinity(numa_node1_cores) else: process.cpu_affinity(numa_node2_cores) def mp_main(task): # 你的并行任务逻辑 pass if __name__ == '__main__': mp_ins = [...] # 你的任务输入列表 num_pools = 92 # 创建Pool时给每个worker传入索引,用于分配核心 with Pool(num_pools, initializer=init_worker, initargs=(0,)) as p: # 手动更新每个worker的初始化参数 for idx, worker in enumerate(p._pool): worker._target = init_worker worker._args = (idx,) worker.start() p.map(mp_main, mp_ins)
方法2:调整父进程的CPU亲和性
先让父进程绑定所有核心,再启动子进程,依赖Windows调度器自动分配到不同NUMA节点:
import psutil import os # 父进程先绑定所有96个核心 parent_process = psutil.Process(os.getpid()) parent_process.cpu_affinity(list(range(96))) # 后续并行代码保持不变 from multiprocessing import Pool def mp_main(task): pass if __name__ == '__main__': mp_ins = [...] num_pools = 92 with Pool(num_pools) as p: p.map(mp_main, mp_ins)
这种方法更简单,但分配精度不如方法1。
方法3:针对内存密集型任务的NUMA优化
如果你的任务涉及大量内存读写,可进一步将任务和对应NUMA节点的内存绑定,避免跨节点内存访问的性能损耗。这需要结合win32api做内存分配控制,适合高性能计算场景。
注意事项
- 确认Windows版本支持NUMA管理(Win10/Server 2016及以上)
- 预留2-4个核心给系统进程,避免系统卡顿
- 若任务是IO密集型,CPU利用率不均可能是IO瓶颈导致,需先排查任务本身的瓶颈
内容的提问来源于stack exchange,提问作者Benny K
相关产品推荐
相关产品推荐

