版本 0.59.0 (2024年1月31日)

这是一个主要的 Numba 版本发布。Numba 现在支持 Python 3.12,请在下方找到所有值得注意项目的摘要。

亮点

Python 3.12 支持

此版本的突出特点是 Numba 正式支持 Python 3.12。

请注意,此版本中(针对 Python 3.12)暂时禁用了性能分析支持,并且在开发过程中已发现若干已知问题。Numba 团队正在积极解决这些问题。请参阅相关问题页面(Numba #9289Numba #9291)以获取正在进行的修复列表和进度更新。

(PR-#9246)

将最低支持的 Python 版本移至 3.9。

已移除对 Python 3.8 的支持,Numba 的最低支持 Python 版本现在是 Python 3.9。

(PR-#9310)

新功能

添加对 ufunc 属性和 reduce 的支持

增加了对 ufunc.reduce 和大多数 ufunc 属性的支持。

(PR-#9123)

添加一个配置变量以启用/禁用 llvmlite 内存管理器

添加了一个配置变量,用于强制启用或禁用 llvmlite 内存管理器。

(PR-#9341)

改进

TargetLibraryInfo 传递添加到 CPU LLVM 管道。

TargetLibraryInfo 过程确保在调用简化期间进行的优化适合目标平台,如果没有这个过程,目标平台将被假定为Linux,代码将被优化以生成例如在Windows上不存在的数学符号。历史上,这个问题通过使用Numba内部库携带包装符号来避免,但这样做可能会损害性能。由于这一变化,Numba内部库变得更小,并且在使用``exp2``和``log2``函数的代码中增加了优化机会。

(PR-#9336)

Numba 弃用警告类现在是内置警告类的子类

为了帮助用户管理和抑制来自 Numba 的弃用警告,NumbaDeprecationWarningNumbaPendingDeprecationWarning 类现在分别是内置 DeprecationWarningPendingDeprecationWarning 的子类。因此,DeprecationWarningPendingDeprecationWarning 上的警告过滤器将适用于 Numba 的弃用警告。

(PR-#9347)

NumPy 支持

添加了对 np.indices() 函数的支持。

添加了对 numpy.indices() 的支持。

(PR-#9126)

添加了对 np.polynomial.polynomial.Polynomial 类的支持。

为包 np.polynomial.polynomial 中的 Polynomial 类添加了支持。

(PR-#9140)

增加了对函数 np.polynomial.polyutils.as_series() 的支持,以及来自 np.polynomial.polynomial 的函数 polydiv()polyint()polyval()

增加了对 np.polynomial.polyutils.as_series()np.polynomial.polynomial.polydiv()``np.polynomial.polynomial.polyint()``(仅前两个参数)、``np.polynomial.polynomial.polyval()``(仅前两个参数)的支持。

(PR-#9141)

添加了对 np.unwrap() 函数的支持。

numpy.unwrap() 添加了支持。仅当 axis 参数的值等于 -1 时才支持该参数。

(PR-#9154)

添加了对检查数据类型是否相等的功能支持。

增加了对检查两个 dtype 对象是否相等的支持,例如 assert X.dtype == np.dtype(np.float64)

(PR-#9249)

CUDA API 变更

增加了对使用C ABI编译设备函数的支持

通过 compile_ptx() API 支持使用 C ABI 编译设备函数,以便更容易与 CUDA C/C++ 和其他语言进行互操作。

(PR-#9223)

使 grid() 和 gridsize() 使用 64 位整数

cuda.grid()cuda.gridsize() 现在使用64位整数,因此当网格包含超过 2 ** 31 个线程时,它们不再溢出。

(PR-#9235)

通过实现使用列表来防止内核被丢弃

使用 nvJitLink 编译和链接时,内核不再被丢弃,因为它们被添加到 @"llvm.used" 列表中。

(PR-#9267)

支持 Windows CUDA 12.0 工具包 conda 包

在Windows上,CUDA工具包12.0的conda包中使用的库路径被添加到检测CUDA库时使用的搜索路径中。

(PR-#9279)

性能提升与变更

改进IR复制速度

FunctionIR 的深度复制进行了改进。在一种情况下,InlineInlineables 过程的速度提高了3倍。

(PR-#9245)

Bug 修复

动态分配 Parfor 调度

此PR修复了一个问题,即并行区域在循环中多次执行。之前的代码使用alloca在栈上分配parfor调度,但如果循环中有许多这样的parfor,则会导致栈溢出。新代码在并行区域前后分别调用Numba并行运行时的分配/释放对。目前,这些调用重定向到malloc/free,尽管其他机制如池化也是可能的,并且可能会在以后实现。此PR还增加了在prange循环未转换为parfor的情况下发出警告。如果循环中有异常控制流,可能会发生这种情况。这些是相关的,因为原始问题中有一个prange循环未转换为parfor,因此prange主体内的所有parfor都在并行运行,每次都增加栈的使用。

(PR-#9048)

@guvectorize 函数中支持多种输出

此PR修复了 Numba #9058 ,现在可以调用具有多个输出的guvectorize。

(PR-#9049)

PythonAPI.call 中修复了对 None 参数的处理。

修复了当 args=None 传递给 PythonAPI.call 时发生的段错误。

(PR-#9089)

修复PHI节点中字面值的传播。

修复了字面量传播过程中一个错误,其中PHI节点可能被错误地替换为常量。

(PR-#9144)

numpy.digitize 实现行为与 numpy 一致

numpy.digitize 的实现已更新,以在更广泛的情况下按照 numpy 的行为方式进行操作,包括在提供的 bins 实际上不是单调的情况下。

(PR-#9169)

numpy.searchsortednumpy.sort 行为更新

  • numpy.searchsorted 的实现已更新,以在更广泛的使用场景中产生与 numpy 相同的输出,包括提供的数组 a 实际上未正确排序的情况。

  • numpy.searchsorted 实现了一个修复,针对 side=’right’ 且提供的数组 a 包含 NaN 的情况。

  • numpy.searchsorted 实现扩展以支持复杂输入。

  • numpy.sort (以及 array.sort) 的实现扩展以支持复杂数据的排序。

(PR-#9189)

修复SSA以考虑变量,其中使用不受定义支配

SSA 问题被修复,使得条件定义的变量将接收一个 phi 节点,表明存在一条路径,其中该变量是未定义的。这会影响依赖 SSA 行为的扩展代码。

(PR-#9242)

修复了 prange 中的 RecursionError

使用 prange 的某些循环模式导致编译器出现 RecursionError 的问题已修复。以下展示了此类循环的一个示例。该问题会导致编译器陷入无限递归循环,试图确定 var1var2 的定义。该模式涉及在 if-else 树中定义变量,但并非所有分支都定义了这些变量。

for i in prange(N):
    for j in inner:
        if cond1:
            var1 = ...
        elif cond2:
            var1, var2 = ...

        elif cond3:
            pass

        if cond4:
            use(var1)
            use(var2)

(PR-#9244)

在 ufunc.reduce 中支持负轴。

修复了 ufunc.reduce 中的一个错误,以正确处理负轴值。

(PR-#9296)

修复 parfor 归约与 Python 3.12 的问题。

parfor 归约代码对它发现的语句顺序有一定的期望,这些期望基于 Numba 先前版本生成的代码。在 Python 3.12 中,过去紧随归约操作符语句(如二元操作)的赋值语句,现在被移到了自己的基本块中。这一变化重新排序了发现的归约节点集合,使得该赋值语句紧随归约操作符之后,就像在之前的 Numba 版本中一样。这仅影响内部的 parfor 归约代码,实际上并不改变 Numba IR。

(PR-#9334)

更改

使测试列表不调用CPU编译。

Numba 的测试列表命令 python -m numba.runtests -l 由于测试套件中某些测试函数的声明方式,历史上会触发 CPU 目标编译。现在已调整为在测试列表时不调用 CPU 目标编译器,并添加了一个测试以确保这种情况保持不变。

(PR-#9309)

由于 Python 3.12 在推导式中的变量遮蔽导致的语义差异

Python 3.12 引入了一个新的字节码 LOAD_FAST_AND_CLEAR,它仅在推导式中使用。它具有 Numba 无法建模的动态语义。

例如,

def foo():
    if False:
        x = 1
    [x for x in (1,)]
    return x  # This return uses undefined variable

变量 x 在返回语句中未定义。Numba 不会引发 UnboundLocalError,而是在编译时如果使用了未定义的变量,会引发 TypingError

然而,Numba 并不能总是检测到未定义的变量。

例如,

def foo(a):
    [x for x in (0,)]
    if a:
        x = 3 + a
    x += 10
    return x

调用 foo(0) 返回 10 而不是引发 UnboundLocalError。这是因为 Numba 在运行时不跟踪变量的生命周期。返回值是 0 + 10,因为 Numba 会将未定义的变量零初始化。

(PR-#9315)

重构并移除遗留的API/测试内部组件。

为了便于一般维护,减少调用编译的可能方式,已移除了一些内部使用的函数,具体包括:

  • numba.core.compiler.compile_isolated 已被移除。

  • numba.tests.support.TestCase::run_nullary_func 已被移除。

  • numba.tests.support.CompilationCache 已被移除。

此外,”嵌套上下文” 的概念已从 numba.core.registry.CPUTarget 中移除,连同其实现细节。目标扩展的维护者(那些使用 numba.core.target_extension 中的 API 来扩展 Numba 对自定义/合成硬件支持的人)应注意,如果存在,同样可以从 numba.core.descriptor.TargetDescriptor 的目标扩展实现中删除。也就是说,nested_context 方法及其相关实现细节可以从自定义目标的 TargetDescriptor 中直接移除。

此外,在重构过程中发现了一个关于记录数组类型的错误。事实证明,仅在可变性上有所不同的两种记录类型可能会混淆,这一问题现已修复。

(PR-#9330)

弃用

显式设置 NUMBA_CAPTURED_ERRORS=old_style 将引发弃用警告

根据旧样式错误捕获的弃用计划,显式设置 NUMBA_CAPTURED_ERRORS=old_style 将引发弃用警告。此版本是最后一个使用“旧样式”作为默认值的版本。详细信息记录在 https://numba.readthedocs.io/en/0.58.1/reference/deprecation.html#deprecation-of-old-style-numba-captured-errors

(PR-#9346)

已过时的弃用

对象模式 回退 支持已被移除。

根据 Numba 0.59.0 的弃用计划,所有 Numba jit 系列装饰器中已移除对“对象模式回退”的支持。此外,nopython 关键字参数的默认值已更改为 True,这意味着所有 Numba jit 系列装饰的函数现在默认将以 nopython 模式编译。

(PR-#9352)

移除已弃用的API @numba.generated_jit

根据 0.59.0 的弃用计划,@numba.generated_jit 的支持已被移除。建议使用 @numba.extending.overload 和高级扩展 API 作为替代。

(PR-#9353)

拉取请求:

作者: