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

使用@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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:32:24