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

为何Numba JIT编译的Python代码性能反而低于原生代码?

为什么Numba JIT编译后的非Numpy代码性能不如原生Python?

1. 没处理Numba的编译预热开销

Numba第一次编译JIT函数时,需要把Python代码转成机器码,这个过程本身要花时间。如果你的基准测试直接计时,没先调用一次JIT函数完成编译(也就是预热),编译时间会被算进总耗时,导致结果看起来比原生代码慢很多。

举个反例:

from numba import jit
import time

@jit(nopython=True)
def numba_square_loop(arr):
    res = []
    for x in arr:
        res.append(x**2)
    return res

# 直接计时,包含编译时间
start = time.time()
numba_square_loop([1,2,3]*1000)
print(time.time() - start)

正确做法是先预热再计时:

# 先调用一次完成编译
numba_square_loop([1,2,3])
# 再正式计时
start = time.time()
numba_square_loop([1,2,3]*1000)
print(time.time() - start)

2. 测试用例规模太小

Numba的优势体现在计算密集、循环次数多的场景。如果你的测试数组只有几百个元素,原生Python的循环开销和JIT的编译+执行开销比起来,差距不明显甚至JIT更慢。只有当循环次数达到百万级以上,Numba编译后的机器码优势才能凸显。

3. 用了Numba不擅长的Python容器

Numba的nopython模式(性能最优模式)对普通Python列表的支持有限。比如在JIT函数里用list.append(),因为Python列表是动态扩容的,涉及内存分配等Python runtime操作,这些操作没法被Numba完全优化,反而不如原生Python对列表的成熟优化。

要让Numba发挥优势,应该用它支持的高效结构,比如numba.typed.List,或者直接用Numpy数组(这也是你Numpy相关实现性能正常的原因)。示例:

from numba import jit, typed

@jit(nopython=True)
def numba_square_typed_list(arr):
    res = typed.List()
    for x in arr:
        res.append(x**2)
    return res

4. 列表推导、map本身已是C级优化

Python的列表推导和map函数是CPython内部用C实现的,性能本来就很高。当操作本身很简单(比如平方计算)时,原生C实现的开销已经极低,Numba的优化空间很小,自然很难超越。

5. 没启用正确的Numba模式

如果没指定nopython=True,Numba默认用object模式,很多操作还是会调用Python runtime,性能提升有限甚至不如原生。必须确保JIT函数启用nopython=True模式(如果无法进入该模式,Numba会抛出警告,需要检查代码里是否有不支持的特性)。


内容的提问来源于stack exchange,提问作者IgorAlves

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:17:37