使用@njit(parallel=True)在新笔记本上代码运行变慢的问题
问题:Numba @njit(parallel=True)在新戴尔Precision笔记本上性能反而下降
近期更换了一台理论性能更优的戴尔Precision笔记本(搭载Intel i7处理器与NVIDIA GPU),但之前在旧笔记本上用@njit(parallel=True)加速的numpy及循环代码,如今运行速度大幅变慢。已安装cudatoolkit与最新版Numba,且配置了CUDA_HOME环境变量,仍不清楚问题所在。
部分函数示例
@njit(parallel=True) def find_nearest(array, value): """ Given an array and a value, this function will find the index position inside the array that matches closest to the value """ array = np.asarray(array) idx = (np.abs(array - value)).argmin() return array[idx] @njit(parallel=True) def rms(y): """ calculates the root mean square of an array """ rms = np.sqrt(np.mean(y**2)) return rms @njit(parallel=True) def dc_normalize(sig_array): """Removes DC and normalizes to -1, 1 range """ sig_array_norm = np.asarray(sig_array.copy()) sig_array_norm -= sig_array_norm.mean() sig_array_norm /= np.absolute(sig_array_norm).max() + 1e-10 return sig_array_norm @njit(parallel=True) def energy(frame): """Computes signal energy """ return np.sum(frame ** 2) / np.float64(len(frame))
测试示例代码
start = datetime.now() @njit(parallel=True) def rms(y): """ calculates the root mean square of an array """ rms = np.sqrt(np.mean(y**2)) return rms x = np.random.rand(100000) result = rms(x) print('with @njit:', datetime.now()-start) start = datetime.now() def rms(y): """ calculates the root mean square of an array """ rms = np.sqrt(np.mean(y**2)) return rms x = np.random.rand(100000) result = rms(x) print('without @njit:', datetime.now()-start)
测试输出结果
with @njit: 0:00:00.253571 without @njit: 0:00:00.004011
排查思路
- 去掉不必要的
parallel=True:你的测试函数(如rms、find_nearest)都是单线程即可高效完成的操作,启用并行反而会带来线程调度、数据拆分的额外开销。Numba的并行仅在函数内存在可并行的独立循环时才有意义,纯numpy内置函数本身已做高度优化,额外加parallel=True只会拖慢速度。 - 修正JIT编译计时方式:测试代码把
@njit装饰的函数放在计时范围内,第一次调用会触发JIT编译,编译时间被计入总耗时。正确做法是先预热函数(调用一次)再计时:@njit(parallel=True) def rms(y): rms = np.sqrt(np.mean(y**2)) return rms # 预热函数 rms(np.random.rand(100)) # 正式计时 start = datetime.now() x = np.random.rand(100000) result = rms(x) print('with @njit (after warmup):', datetime.now()-start) - 验证CUDA实际使用情况:当前这些函数用的是CPU版
@njit,并未调用GPU。如果想利用NVIDIA GPU加速,需要改用Numba的CUDA API编写核函数,而非给CPU函数加parallel=True。 - 检查笔记本性能模式:戴尔Precision可能默认开启节能模式限制CPU主频,切换到“高性能”电源模式,确保CPU能满负荷运行。
- 对比Numba版本差异:最新版Numba可能存在兼容性问题,或旧笔记本的Numba版本对旧CPU优化更好,可尝试降级到旧笔记本使用的Numba版本测试性能变化。
- 检查并行后端依赖:Numba默认用
omp作为并行后端,确认新笔记本是否安装了OpenMP库(如Visual Studio C++ Runtime或GCC的OpenMP组件),缺失会导致Numba回退到低效并行实现。 - 分析函数执行瓶颈:用
cProfile或Numba的调试工具(如@njit(debug=True))定位函数内的耗时部分,确认是编译还是执行阶段拖慢了速度。
内容的提问来源于stack exchange,提问作者spiderlouie
相关产品推荐
相关产品推荐

