Numba 0.59.0 发布详解Python 3.12 支持、nopython 默认化与 CUDA/NumPy 新能力【免费下载链接】numbaNumPy aware dynamic Python compiler using LLVM项目地址: https://gitcode.com/gh_mirrors/nu/numba导读Numba 0.59.0 是 2024 年 1 月 31 日发布的一个里程碑式 major 版本它正式支持 Python 3.12将最低支持版本提升至 Python 3.9并按照既定弃用计划移除了 object mode fall-back、让jit系列装饰器默认以nopython模式编译。与此同时该版本在 NumPy 函数覆盖np.indices、np.unwrap、多项式函数族、ufunc 属性与ufunc.reduce、CUDA C ABI 设备函数编译、LLVM 编译管线优化以及一批并行parfor/prange缺陷修复上均有实质性进展。阅读本文后你将完整掌握 0.59.0 的变更全貌、迁移要点与底层实现原理并能据此规划从旧版本升级或适配 Python 3.12 的具体方案。版本概况与支持矩阵变化正式支持 Python 3.120.59.0 最突出的特性是对 Python 3.12 的官方支持对应 PR #9246。为适配 Python 3.12 的新字节码语义本版本付出了一系列配套改动包括修复 parfor reduction 在 Python 3.12 下的顺序假设见 PR #9334 相关变更处理新增字节码LOAD_FAST_AND_CLEAR带来的推导式语义差异GPU CI 全面覆盖 Python 3.9–3.12PR #9318、#9325。需要特别注意的是Python 3.12 下的 profiling 支持在本版本中暂时被禁用且开发过程中发现了一些已知问题官方仍在持续修复中相关跟踪见 PR #9289、#9291。如果项目依赖 cProfile 对 jit 函数做性能剖析在升级到 0.59.0 并切换 Python 3.12 前应做好回归验证。最低 Python 版本提升至 3.9依据 0.59.0 的版本支持计划对 Python 3.8 的支持已被移除PR #9310当前支持范围为Python 3.9 / 3.10 / 3.11 / 3.12。仍在 Python 3.8 环境运行的用户需要先升级解释器版本再升级 Numba。重大架构变更object mode fall-back 移除与 nopython 默认化这是 0.59.0 对用户影响面最大的一项变更PR #9352。按弃用计划object mode fall-back 支持已从所有jit系列装饰器中移除同时nopython关键字参数的默认值被改为True这意味着所有jit、njit装饰的函数默认即按 nopython 模式编译不再存在编译失败后自动回退到对象模式的行为。对既有代码的影响过去依赖jit静默回退的代码现在会在类型推断失败时直接抛出TypingError建议显式使用njitnumba.jit(nopythonTrue)以明确意图并在升级后运行完整测试套件逐个修复报错的函数如需对象模式支持可显式传nopythonFalse但已无 fall-back 机制需自行处理混合模式。与之一同按计划移除的还有numba.generated_jit装饰器PR #9353官方推荐改用 numba.core.extending 中的overload及高层扩展 API 作为替代方案例如 overloading-guide.rst 中所描述的实现方式。新功能详解ufunc 属性与ufunc.reduce支持0.59.0 为 Numba 的 DUFunc动态 ufunc补充了大部分 ufunc 属性以及ufunc.reducePR #9123。在源码层面这一能力体现在 numba/np/ufunc/dufunc.py 中_install_ufunc_reduce与_install_ufunc_reduceat将 reduce/reduceat 方法安装到 DUFunc 对象上并由 numba/np/ufunc/_internal.c 中的dufunc_reduce/dufunc_reduceat等 C 桥接函数转发到底层 ufunc 调度。实际使用示例import numpy as np import numba as nb nb.vectorize def add(a, b): return a b # 对 DUFunc 直接调用 reduce result add.reduce(np.arange(10)) # 等价于 np.add.reduce(np.arange(10))同时ufunc.reduce对负数 axis的处理缺陷也在本版本修复PR #9296负轴现在会被正确解析并支持非法 axis 也会得到与 NumPy 一致的报错行为。新增 llvmlite 内存管理器开关配置0.59.0 新增一个配置变量用于强制启用或禁用 llvmlite 内存管理器PR #9341。该配置允许用户在遇到与 LLVM 内存分配相关的疑难问题时手动切换行为具体通过环境变量形式设置。这为排查 llvmlite 与系统分配器之间的交互问题提供了一个可控的调试开关详见 envvars.rst 中关于 Numba 环境变量的说明。NumPy 支持扩充新增np.indices()支持numpy.indices()已可在 nopython 模式下使用PR #9126其实现位于 numba/np/arrayobj.py 的数组构造相关路径中返回的网格索引数组与 NumPy 语义一致import numpy as np from numba import njit njit def mesh(n, m): return np.indices((n, m)) print(mesh(2, 3))新增np.unwrap()支持numpy.unwrap()已被支持PR #9154。需要注意限制axis参数仅在取值为 -1 时被支持其他 axis 取值目前仍会报错。默认行为沿最后一个轴展开角度可直接使用from numba import njit import numpy as np njit def unwrap_angles(a): return np.unwrap(a)多项式函数族支持np.polynomial.polynomial.Polynomial类0.59.0 支持在 nopython 模式下使用该多项式类PR #9140可进行多项式的构造、求值等操作函数级支持PR #9141np.polynomial.polyutils.as_series()np.polynomial.polynomial.polydiv()np.polynomial.polynomial.polyint()——仅支持前两个参数np.polynomial.polynomial.polyval()——仅支持前两个参数。相关实现可参考 numba/np/polynomial 目录下的代码测试用例位于 test_polynomial.py。dtype 相等性判断现在可以在 nopython 模式下直接比较两个 dtype 对象是否相等PR #9249例如from numba import njit import numpy as np njit def check_dtype(arr): return arr.dtype np.dtype(np.float64)这在泛型核函数中根据数组 dtype 分支处理时非常实用。CUDA API 变更支持以 C ABI 编译设备函数compile_ptx()API 现在支持以C ABI编译设备函数便于与 CUDA C/C 及其他语言互操作PR #9223。在 numba/cuda/compiler.py 中可以看到compile_ptx的实现其默认abinumba以 Numba ABI 编译 kernel但可以通过abic切换为 C ABI与之配套的还有compile_ptx_for_current_device针对当前设备的 compute capability 编译。相关文档参见 cuda_ffi.rst 与 cuda-reference/host.rst。grid()与gridsize()改用 64 位整数cuda.grid()和cuda.gridsize()的返回值改为 64 位整数PR #9235当网格总线程数超过2 ** 31时不再溢出。对绝大多数应用这是透明升级但若代码中将这些返回值窄化到 32 位整型变量需注意类型调整。防止 kernel 被 nvJitLink 丢弃通过将 kernel 加入llvm.used列表PR #9267修复了使用 nvJitLink 编译和链接时 kernel 可能被当作无用符号丢弃的问题。这对依赖 JIT 链接如预编译 LTO-IR 链接场景的用户非常重要。Windows 下 CUDA 12.0 conda 包支持CUDA toolkit 12.0 的 conda 包在 Windows 上的库搜索路径已加入 CUDA 库检测逻辑PR #9279在 Windows conda 环境中使用 CUDA 12.0 时不再出现库找不到的问题。编译管线与性能改进CPU LLVM 管线新增TargetLibraryInfopass0.59.0 在 CPU 的 LLVM 编译管线中加入了TargetLibraryInfopassPR #9336见 numba/core/codegen.py 与 numba/core/cpu.py 相关管线配置。该 pass 确保调用简化call simplification阶段的优化决策匹配真实目标平台此前若缺少该 pass目标会被假定为 Linux导致在 Windows 上可能生成不存在的数学符号历史上 Numba 通过内部库携带包装符号来规避该问题但会损害性能加入该 pass 后Numba 内部库更精简且使用exp2、log2等函数的代码获得了更多优化机会。IR 复制速度提升对FunctionIR的深拷贝deepcopy做了优化PR #9245。据发布说明在一个典型场景中InlineInlineablespass 提速约 3 倍这对包含大量内联调用的编译任务能带来可感知的编译延迟下降。弃用警告类继承内置警告类NumbaDeprecationWarning和NumbaPendingDeprecationWarning现在是内置DeprecationWarning与PendingDeprecationWarning的子类PR #9347。在 numba/core/errors.py 中可以看到其类定义class NumbaDeprecationWarning(NumbaWarning, DeprecationWarning): pass class NumbaPendingDeprecationWarning(NumbaWarning, PendingDeprecationWarning): pass由此针对内置弃用警告的过滤器如warnings.filterwarnings(ignore, categoryDeprecationWarning)或-W ignore::DeprecationWarning现在同样会作用于 Numba 的弃用警告简化了告警治理。Bug 修复深入并行区域调度动态分配修复栈溢出此前的 parfor 调度结构通过 alloca 在栈上分配当并行区域prange 循环体被执行很多次时栈会持续累积直至溢出PR #9048。新实现改为在并行区域前后分别调用 Numba 并行运行时numba/core/runtime的分配/释放对当前映射为malloc/free未来可替换为内存池等机制。同时当 prange 循环因存在异常控制流而无法转换为 parfor 时现在会给出警告避免静默退化。guvectorize支持多输出修复了 Numba #9058 相关的问题现在可以调用具有多个输出参数的guvectorize函数PR #9049。PythonAPI.call的None参数处理修复了向PythonAPI.call传递argsNone时的段错误PR #9089现在可以安全地以空参数调用。PHI 节点字面量传播修复修复了字面量传播literal propagationpass 中 PHI 节点被错误替换为常量的问题PR #9144。此问题会导致条件分支汇聚处变量值被错误折叠影响依赖该 pass 的扩展代码。NumPy 行为对齐numpy.digitize更新实现以在更广泛的场景下与 NumPy 行为一致包括 bins 并非单调的情况PR #9169numpy.searchsorted与numpy.sortPR #9189searchsorted在输入数组a未正确排序时也能与 NumPy 输出一致修复sideright且a含 NaN 时的行为searchsorted扩展支持复数输入sort及array.sort扩展支持复数数据排序。SSA 定义域修复修复了 SSA 构建中变量使用未被定义支配的问题PR #9242条件定义的变量现在会获得 PHI 节点标明存在变量未定义的路径。这对依赖 SSA 行为的扩展代码有影响。prange 中的RecursionError修复修复了特定循环模式下编译器陷入无限递归的问题PR #9244。触发模式是在 if-else 树中部分分支定义变量、部分分支未定义例如from numba import njit, prange njit(parallelTrue) def f(N, inner, cond1, cond2, cond3, cond4): 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)编译器此前会反复尝试确定var1/var2的定义而陷入递归循环现已被修复。parfor reduction 适配 Python 3.12Python 3.12 中原本紧跟在归约运算语句如 binop之后的赋值被移到了独立的基本块破坏了 parfor reduction 对语句顺序的既有假设PR #9334。修复仅调整了内部 parfor reduction 节点发现与重排逻辑不改变 Numba IR 本身。行为变更与语义差异测试列表命令不再触发 CPU 编译python -m numba.runtests -l列出测试历史上会因测试函数声明方式触发 CPU 目标编译现在已修复PR #9309并新增测试防止回归。Python 3.12 推导式变量遮蔽的语义差异Python 3.12 新增字节码LOAD_FAST_AND_CLEAR仅在推导式中使用其动态语义 Numba 无法建模PR #9315。举例def foo(): if False: x 1 [x for x in (1,)] return x # 此 return 使用未定义变量此处x在 return 处未定义。与 CPython 抛UnboundLocalError不同Numba 会在编译期抛出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得到10。升级到 0.59.0 并运行于 Python 3.12 时应审查代码中是否有这种依赖推导式清空外部变量的隐晦模式。遗留 API 移除一批内部 API 已被删除PR #9330以减少编译入口的多样性、降低维护成本numba.core.compiler.compile_isolated已移除numba.tests.support.TestCase.run_nullary_func已移除numba.tests.support.CompilationCache已移除numba.core.registry.CPUTarget的 nested context 概念及实现细节已移除。自定义 target 扩展使用 numba/core/target_extension.py 的 API若在TargetDescriptor中实现了nested_context方法应一并删除。该重构还顺带修复了一个 record 数组类型化缺陷两个仅在可变性上不同的 record 类型此前可能发生别名alias现已修复。弃用与过期弃用NUMBA_CAPTURED_ERRORSold_style弃用警告按旧式错误捕获的弃用时间表显式设置NUMBA_CAPTURED_ERRORSold_style现在会触发弃用警告PR #9346。0.59.0 是最后一个以old_style为默认值的版本后续版本将切换默认值建议用户尽快显式设置NUMBA_CAPTURED_ERRORSnew_style并验证程序行为相关历史背景可参见 0.58.0 发布说明 与 deprecation.rst。已过期并移除的弃用项弃用项状态替代方案object mode fall-back已移除0.59.0nopythonTrue显式编译对象模式需显式nopythonFalsenumba.generated_jit已移除0.59.0numba.extending.overload与高层扩展 API基础设施与维护towncrier 变更文件验证脚本新增对用户提交的 towncrier.rst变更文件的验证能力PR #9335脚本位于 maint/towncrier_checker.py 与 maint/towncrier_rst_validator.py该脚本会随 towncrier GitHub 工作流在每个 PR 上自动运行确保 news 文件格式合法。此外还引入了用于发现缺失 towncrier news 文件的辅助脚本PR #9101并新增了 power-on-self-test 脚本用于 CIPR #9191。其他维护性变更包括升级至 cloudpickle 3.0.0PR #9307、修复若干测试隔离与类型检查问题PR #9403、修正 RVSDG 测试切片配置PR #9360等详见 0.59.0 发布说明全文。升级建议总结解释器层面确认 Python 版本在 3.9–3.12 之间若使用 Python 3.12注意 profiling 暂不可用并审查推导式变量遮蔽相关代码。编译模式层面由于 object mode fall-back 已移除jit现在默认nopythonTrue升级后请运行完整测试将依赖回退的代码显式改造。API 层面移除generated_jit用法改用overload删除自定义 target 中的nested_context。环境变量层面尽快切换到NUMBA_CAPTURED_ERRORSnew_style关注新增的 llvmlite 内存管理器开关配置见 envvars.rst。并行代码层面验证 prange/parfor 代码的栈使用与归约行为若出现prange 未转换为 parfor的警告检查循环内是否存在异常控制流。【免费下载链接】numbaNumPy aware dynamic Python compiler using LLVM项目地址: https://gitcode.com/gh_mirrors/nu/numba创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考