scipy.optimize.curve_fit集群运行CPU占用超100%异常问题咨询
问题原因
- 该现象不属于异常错误,本质是scipy、numpy底层默认调用了多线程线性代数运算库(常见的如OpenBLAS、MKL、ATLAS),这类库会自动调度CPU多核资源做并行计算,top统计的CPU使用率是所有核心占用的总和,单进程超过100%属于正常情况,比如占用2个核心就能达到200%左右的使用率。
- top命令的
TIME+列统计的是进程所有线程的CPU占用时间总和,多核并行场景下,总和自然会大于实际运行的墙上时间(即用户感知到的代码运行时长),比如2个核心同时跑10秒,TIME+就会显示20秒左右的数值。 - 你使用的
curve_fit的trf算法涉及大量矩阵运算、雅可比矩阵求解操作,刚好会触发底层线性代数库的多线程并行逻辑,所以会出现你观察到的现象。
规避方法
如果不需要多线程运行,想要控制CPU使用率,可以通过环境变量手动限制底层库的线程数:
- 限制OpenBLAS线程数:运行代码前在终端执行
export OPENBLAS_NUM_THREADS=1 - 限制MKL线程数:运行代码前在终端执行
export MKL_NUM_THREADS=1 - 通用限制方式:也可以设置
export OMP_NUM_THREADS=1,覆盖所有基于OpenMP实现的并行库的线程数 - 也可以在Python代码最开头(导入numpy、scipy之前)就设置环境变量,示例如下:
import os os.environ['OPENBLAS_NUM_THREADS'] = '1' os.environ['MKL_NUM_THREADS'] = '1' os.environ['OMP_NUM_THREADS'] = '1' import numpy as np from scipy.optimize import curve_fit
如果是提交到集群调度的作业,直接在作业提交脚本里添加对应环境变量的设置即可。
另外可以优化代码本身减少不必要的资源占用:
- 生成data的Python循环可以替换为numpy向量化操作,运行速度能提升数十倍
- 你设置的
max_nfev = 10000000数值过大,仅2个参数的拟合不需要这么高的迭代上限,适当调小可以避免异常场景下的算力浪费 - 你当前设置的拟合边界存在逻辑问题:freq参数的上限设为
20.0*pars[idat][1],但pars[idat][1]是t1的真实值,和freq的量级不匹配,可能导致拟合收敛变慢,建议检查边界设置的合理性。
内容的提问来源于stack exchange,提问作者Djole
相关产品推荐
相关产品推荐

