双处理器Windows机器上multiprocessing无法充分利用CPU的问题
双CPU Windows机器上Python multiprocessing无法充分利用全部核心的问题
我在一台双处理器Windows机器上,尝试使用multiprocessing库运行多个独立Python进程,以最大化利用双CPU来缩短计算时间。机器配置如下:
- 操作系统:Windows 10 Pro for Workstations
- 内存:524 GB
- 硬盘:Samsung SSD PRO 960(NVMe)
- CPU:两颗Xeon Gold 6154(共72核心)
我用Python 3.6执行主脚本,通过multiprocessing库生成72个内存独立的工作进程。初始阶段,机器的72个核心均以100%负载运行,但约5-10分钟后,第二颗CPU的36个核心使用率降至0%,而第一颗CPU的36个核心仍保持100%负载,我无法找到原因。
请问在双处理器Windows机器上使用双CPU时,我是否遗漏了什么配置?如何确保机器的全部性能被充分利用?另外,我好奇如果换成Linux操作系统,情况是否会有所不同?感谢您的帮助。
我的Python主脚本示例如下:
import pandas as pd import netCDF4 as nc from multiprocessing import Pool WEATHERDATAPATH = "C:/Users/..../weatherdata/weatherfile_%s.nc4" OUTPUTPATH = "C:/Users/....outputs/result_%s.nc4" def calculationFunction(year): dataset = nc.Dataset(WEATHERDATAPATH%year) # Read the data data1 = dataset["windspeed"][:] data2 = dataset["pressure"][:] data3 = dataset["temperature"][:] timeindex = nc.num2date(dataset["time"][:], dataset["time"].units) # Do computations with the data, primarily relying on NumPy data1Mean = data1.mean(axis=1) data2Mean = data2.mean(axis=1) data3Mean = data3.mean(axis=1) # Write result to a file result = pd.DataFrame( { "windspeed":data1Mean, "pressure":data2Mean, "temperature":data3Mean, }, index=timeindex ) result.to_csv(OUTPUTPATH%year) if __name__ == '__main__': pool = Pool(72) results = [] for year in range(1900,2016): results.append( pool.apply_async(calculationFunction, (year, ))) for r in results: r.get()
问题分析与解决方案
1. Windows下CPU亲和性的核心问题
这大概率是Windows的NUMA节点亲和性继承导致的:当你的主进程启动时,默认绑定在第一颗CPU对应的NUMA节点上,后续multiprocessing.Pool创建的子进程会自动继承这个亲和性设置。初始阶段系统可能临时调度到第二颗CPU,但一段时间后调度器会把所有进程收拢到主进程的NUMA节点,导致第二颗CPU闲置。
解决这个问题的关键是手动解除进程的亲和性限制,你可以用两种方式:
- 临时方案:任务管理器调整
右键点击Python主进程 → 「设置相关性」→ 勾选所有72个CPU核心,再重新运行脚本。 - 代码方案:用psutil库永久设置
安装psutil后,在子进程启动时强制设置全核心亲和性:import psutil import pandas as pd import netCDF4 as nc from multiprocessing import Pool WEATHERDATAPATH = "C:/Users/..../weatherdata/weatherfile_%s.nc4" OUTPUTPATH = "C:/Users/....outputs/result_%s.nc4" def set_full_affinity(): proc = psutil.Process() # 设置当前进程可使用所有72个核心 proc.cpu_affinity(list(range(72))) def calculationFunction(year): set_full_affinity() # 子进程启动后立即调整亲和性 dataset = nc.Dataset(WEATHERDATAPATH%year) # 后续计算逻辑保持不变... data1 = dataset["windspeed"][:] data2 = dataset["pressure"][:] data3 = dataset["temperature"][:] timeindex = nc.num2date(dataset["time"][:], dataset["time"].units) data1Mean = data1.mean(axis=1) data2Mean = data2.mean(axis=1) data3Mean = data3.mean(axis=1) result = pd.DataFrame( { "windspeed":data1Mean, "pressure":data2Mean, "temperature":data3Mean, }, index=timeindex ) result.to_csv(OUTPUTPATH%year) if __name__ == '__main__': set_full_affinity() # 主进程先设置全核心亲和性 pool = Pool(72) results = [] for year in range(1900,2016): results.append( pool.apply_async(calculationFunction, (year, ))) for r in results: r.get()
2. 排查IO与内存的潜在瓶颈
虽然你的硬件配置很强,但还是要排除两个可能的干扰项:
- IO瓶颈:多个进程同时写入CSV文件可能引发IO等待,看起来像是核心闲置。可以尝试先把计算结果存在内存,最后批量写入,或者改用Parquet这类更高效的文件格式替代CSV。
- NUMA内存分配倾斜:如果第一颗CPU对应的NUMA节点内存被占满,系统可能会把进程都调度到该节点。你可以通过任务管理器的「性能」标签查看两个NUMA节点的内存使用情况,不过524GB内存的话这种概率很低。
3. Linux系统的差异
在Linux下,这种问题大概率不会出现:
- Linux内核的NUMA调度策略更智能,会自动将进程调度到靠近其内存分配的节点,默认不会限制子进程的CPU亲和性;
- 针对Xeon这类服务器CPU,Linux的进程调度器对多CPU、多核心的支持更成熟,能更均衡地利用所有硬件资源;
- 如果你长期需要这类大规模并行计算任务,迁移到Linux(比如CentOS、Ubuntu Server)会获得更稳定的性能表现。
总结
- 优先解决CPU亲和性问题,这是最可能的根源;
- 优化文件读写逻辑,排除IO瓶颈;
- 长期来看,Linux系统在多CPU利用上的表现会比Windows更稳定高效。
内容的提问来源于stack exchange,提问作者Severin
相关产品推荐
相关产品推荐

