尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Numba 0.59.1 版本解析:np.searchsorted 性能回归与 datetime64/NaT 修复、CUDA 内核缓存及 PEP-695 语法支持

Numba 0.59.1 版本解析:np.searchsorted 性能回归与 datetime64/NaT 修复、CUDA 内核缓存及 PEP-695 语法支持 编译器高性能计算【免费下载链接】numbaNumPy aware dynamic Python compiler using LLVM项目地址https://gitcode.com/gh_mirrors/nu/numba点击查看免费下载导读Numba 0.59.1 是紧随 0.59.0 发布的一个 bug-fix 版本专门用于修复 0.59.0 引入的回归问题release note 原文明确说明This is a bug-fix release to fix regressions in 0.59.0见 docs/source/release/0.59.1-notes.rst。本篇文章将逐条拆解该版本中np.searchsorted的性能回归修复、np.datetime64/NaT值处理修复、CUDA 内核缓存含 cooperative group sync修复、Python 3.12 PEP-695 类型参数语法支持等核心变更并结合当前仓库源码numba/np/arraymath.py、numba/tests/test_np_functions.py、numba/tests/test_npdatetime.py等深入剖析其底层实现与验证方式帮助你理解这些 bug 的产生原因、修复机制以及如何在自己的 Numba 代码中规避同类问题。一、版本概览一次聚焦回归的 bug-fix 发布Numba 0.59.1 于 2024 年 3 月 18 日发布与前一个版本 0.59.0 的间隔很短目的非常明确集中修复 0.59.0 引入的回归regression问题。整个版本共包含 7 个合并的 Pull-RequestPR #9445、#9447、#9448、#9449、#9450、#9459、#9491主要由sklam、gmarkall、guilhermeleobas、loicdtx四位开发者贡献。从变更内容看该版本的主要工作集中在三个方向np.searchsorted相关修复占两处性能回归修复 datetime64/NaT支持修复CUDA 后端修复内核缓存kernel caching对 target-specific overloads 的支持Python 3.12 兼容性PEP-695 类型参数语法的解析支持。此外还包含 CI/CD 与内部稳定性修复移除已废弃的 CondaEnvironment1、修复 gpuci 版本配置、修复 SSA 阶段非确定性 bug。二、np.searchsorted性能回归修复找回二分查找应有的速度2.1 回归背景Numba 0.59 重构了np.searchsorted的实现但引入了一个明显的性能回归使该函数变得明显变慢release note 原文Fixed a performance regression introduced in Numba 0.59 which madenp.searchsortedconsiderably slower。该问题由 PR #9448 修复。2.2 源码级剖析当前的二分查找实现当前仓库中np.searchsorted的 nopython 模式实现位于 numba/np/arraymath.pyL4512-L4610。其核心是_searchsorted工厂函数本质上是 NumPy 内部 C 实现npysort/binsearch.cpp的忠实移植def _searchsorted(cmp): # a facsimile of numpy/core/src/npysort/binsearch.cpp def impl(a, key_val, min_idx, max_idx): while min_idx max_idx: # to avoid overflow mid_idx min_idx ((max_idx - min_idx) 1) mid_val a[mid_idx] if cmp(mid_val, key_val): min_idx mid_idx 1 else: max_idx mid_idx return min_idx, max_idx return impl值得注意的几个实现细节防溢出写法中点计算使用min_idx ((max_idx - min_idx) 1)而非(min_idx max_idx) // 2避免大索引相加溢出与 NumPy 源码保持一致比较函数注入二分搜索的行为完全由注入的cmp比较函数决定这为后续datetime64/NaT特殊处理留下了扩展点数组输入优化当查询值v是数组时实现利用输入已排序时搜索区间可以收缩的特性通过last_key_val记录上一个键值若当前键值大于上一个键值则沿用已有区间max_idx len(a)否则重置区间min_idx 0从而显著减少二分查找的范围。这一优化逻辑位于searchsortedoverload 的数组分支numba/np/arraymath.py L4578-L4601。2.3 回归修复的验证方式回归修复通过测试保证在 numba/tests/test_np_functions.py 的test_searchsortedL1508 起中分别用默认sideleft、sideleft、sideright三种包装函数对整数数组含 NaN 的浮点数组做标量、数组、序列三种查询形态的逐一对比验证同时断言非法side值与非常量side值会抛出TypingError。# 测试辅助函数test_np_functions.py L90-L99 def searchsorted(a, v): return np.searchsorted(a, v) def searchsorted_left(a, v): return np.searchsorted(a, v, sideleft) def searchsorted_right(a, v): return np.searchsorted(a, v, sideright)三、np.searchsorted对np.datetime64与NaT的支持修复3.1 两个问题的来源PR #9445对应 issue #9427修复了np.searchsorted的两类问题np.datetime64支持回归0.59 的重构破坏了np.datetime64类型的排序搜索支持NaT值处理错误对Not-a-TimeNaT即 datetime64/timedelta64 的缺失值标记的比较行为与 NumPy 不一致导致排序结果错误。3.2 源码级剖析NaT 感知比较函数修复的核心在于为datetime64/timedelta64类型专门实现了NaT 感知的比较函数位于 numba/np/arraymath.py L4494-L4509register_jitable def _less_then_datetime64(a, b): # Original numpy code is at: numpy/_core/src/npysort/npysort_common.h if np.isnat(a): return 0 if np.isnat(b): return 1 return a b register_jitable def _less_then_or_equal_datetime64(a, b): return not _less_then_datetime64(b, a)该实现的关键语义与 NumPy 保持一致NaT视为小于一切有效时间值当a是NaT时a b恒为 FalseNaT不小于任何值当b是NaT时a b恒为 TrueNaT NaT的陷阱由于_less_then_or_equal_datetime64(a, b) not _less_then_datetime64(b, a)两个NaT比较会得出小于等于为真的结论这与 NumPy 1.16 之后所有 NaT 大小比较含相等均为 False的语义需要结合具体调用场景看待实现上完全复刻了 NumPy 排序代码的行为。3.3 分派逻辑按 dtype 选择比较函数make_searchsorted_implementation函数numba/np/arraymath.py L4533-L4558根据类型选择比较器def make_searchsorted_implementation(np_dtype, side): assert side in VALID_SEARCHSORTED_SIDES if np_dtype.char in mM: # is datetime lt _less_then_datetime64 le _less_then_or_equal_datetime64 else: lt _less_than le _less_than_or_equal if side left: _impl _searchsorted(lt) _cmp lt else: if np.issubdtype(np_dtype, np.inexact) and numpy_version (1, 23): # change in behaviour for inexact types introduced by numpy#21867 _impl _searchsorted(le) _cmp lt else: _impl _searchsorted(le) _cmp le return register_jitable(_impl), register_jitable(_cmp)关键点dtype 判定通过np_dtype.char in mM判断是否为datetime64M或timedelta64m命中即切换到 NaT 感知比较side语义sideleft使用严格小于比较ltsideright使用小于等于比较leNumPy 版本兼容对于非精确类型inexact且 NumPy 版本低于 1.23 时保留了旧行为分支比较器与返回的_cmp分离以兼容 NumPy 1.23 引入的排序行为变化类型提升在searchsortedoverload 入口L4575a与v的 dtype 会先经np.promote_types统一确保混合类型输入也能正确分派。3.4 测试验证该修复有专门的测试覆盖numba/tests/test_np_functions.py 的test_searchsorted系列覆盖整数、浮点含 NaN、复数test_searchsorted_complexL1688以及无序数组输入numba/tests/test_npdatetime.py 的test_searchsorted_datetimeL1153-L1175从test_np_functions复用三个搜索函数对_get_testcases()生成的datetime64测试用例先排序、再分别用标量与数组查询值做逐项对比确保 nopython 模式结果与 Python 参考实现assertPreciseEqual完全一致。3.5 实战提醒在 nopython 模式下使用np.searchsorted时注意side必须是编译期常量字符串left或right运行时传入变量会触发TypingError见 numba/tests/test_np_functions.py L1577-L1582 的nonconst_side用例a需为已排序数组二分查找不校验有序性对含NaT的时间数组Numba 0.59.1 起的排序语义与 NumPy 对齐可作为 NumPy 行为的安全替代。四、CUDA 内核缓存修复支持 target-specific overloads含 cooperative group sync4.1 修复内容PR #9447对应 issue #9432修复了使用 target-specific overloads 的 CUDA 内核无法缓存的问题。此前若内核代码中调用了仅针对特定 target如 CUDA定义的 overload内核缓存kernel caching会失败或行为异常。这一修复使得cooperative group syncCG sync场景也能正常工作——因为 CG sync 在 0.59 中正是通过 target-specific overload 机制实现的。4.2 原理为什么 target-specific overload 会破坏缓存在 Numba 的类型分派体系中overload可以为不同 target 提供不同实现。内核的缓存机制在首次编译后会把编译产物含 typing 结果序列化保存而当 typing 过程中引入了依赖具体 target 才能解析的 overload 时缓存键/序列化逻辑必须能正确记录这一 target 上下文否则缓存命中时会用错误的实现。0.59.1 修复了该序列化/缓存流程中对 target-specific overload 的遗漏。4.3 仓库佐证CUDA 缓存相关代码位于 numba/cuda/compiler.py 与 numba/cuda/dispatcher.py其中numba/cuda/compiler.py同时是 CG sync 相关重载的注册入口之一。对应的测试见 numba/cuda/tests/cudapy/test_caching.py 与 numba/cuda/tests/cudapy/test_cooperative_groups.py。如果你的 CUDA 内核使用了cuda.cg.sync_gridcooperative groups并开启磁盘缓存0.59.1 是修复此类问题的推荐版本。五、Python 3.12 PEP-695 类型参数语法支持5.1 修复内容Python 3.12 引入了 PEP-695 的泛型类型参数语法例如def fT: int - T: return aNumba 0.59.1PR #9459修正了对该语法的解析使 Numba不再错误拒绝使用新语法定义的函数。需要明确的是此版本 Numba 并不利用类型参数做任何高级推导只是让能用新语法写函数这件事不再报错。5.2 测试佐证numba/tests/test_exceptions.py L315-L325 中保留了对 PEP-695 语法函数的异常定位测试包括跨行写法的变体验证在支持 Python 3.12 的环境下带类型参数语法的函数能被正确解析并进入后续编译/异常处理流程py312_pep695_raise def fT: int - T:\n assert a ! 1 py312_pep695_raise_2 def fT: int\n - T:\n assert a ! 15.3 使用注意该支持依赖于运行时的 Python 版本只有在 Python 3.12 上定义的 PEP-695 语法函数才能被解析目前类型参数本身不参与Numba 的类型推断文档明确does not yet take advantage of type parameters建议在生产代码中仍以普通njit函数为主PEP-695 语法仅用于保证不被拒绝。六、其余修复构建链路与编译器稳定性除上述面向用户的功能修复外0.59.1 还包含三项基础设施级变更PR内容影响#9449移除已废弃的CondaEnvironment1清理 CI 依赖消除 GitHub Actions 弃用警告见 buildscripts/azure/azure-linux-macos.yml 等相关 CI 配置#9450修复 gpuci 版本配置修正 GPU CI 使用的版本矩阵相关配置见 buildscripts/gpuci/axis.yaml#9491修复 SSA 阶段不稳定导致的非确定性 bug修复由 SSA静态单赋值变换顺序不稳定引起的偶发非确定性编译问题核心实现在 numba/core/ssa.py其中 #9491 尤其值得关注非确定性 bug 是最难排查的一类问题其根源是 SSA 变换过程中对同名变量/块的排序不稳定导致不同运行产生不同的 IR 与代码生成结果。修复后编译器在多次运行同一输入时会得到一致的输出从而保证缓存命中与结果可复现。七、升级建议与结论升级路径如果你正在使用 0.59.0 且受以下任一问题影响建议升级到 0.59.1nopython 模式下np.searchsorted性能明显变慢或对datetime64/含NaT数组的搜索行为与 NumPy 不一致CUDA 内核使用 target-specific overload尤其是 cooperative group sync且开启缓存后出现缓存失效、重复编译或错误结果在 Python 3.12 上使用 PEP-695 语法定义函数被 Numba 拒绝遇到偶发、不可复现的编译结果差异SSA 非确定性。版本衔接0.59.1 之后官方继续在 0.60、0.61 及后续版本中演进见 docs/source/release 目录下的各版本发布说明。作为 0.59 系列的收尾版本它扮演了稳定 0.59 主干的角色其修复模式回归修复 专项测试 语义对齐 NumPy也是理解 Numba 后续版本np.searchsorted、datetime 支持与 CUDA 缓存演进的良好起点。赞分享编译器高性能计算【免费下载链接】numbaNumPy aware dynamic Python compiler using LLVM项目地址https://gitcode.com/gh_mirrors/nu/numba点击查看免费下载相关推荐Numba CUDA Python 支持特性全解析内核语言、内置函数与 NumPy 子集指南Numba CUDA Python 支持特性全解析内核语言、内置函数与 NumPy 子集指南 CUDA Python 是 Numba 面向 NVIDIA GP编译器高性能计算pytest 2.6.1 版本解析xfail 支持期望异常与回归修复指南pytest 2.6.1 版本解析xfail 支持期望异常与回归修复指南 导读 本文围绕 pytest 2.6.1 版本发布说明展开聚焦该版本引入的核心新特测试开发工具ClickHouse v26.2.9.9-stable 版本详解INSERT 去重性能回归修复、cgroupv2 内存追踪改进与关键 Bug 修复ClickHouse v26.2.9.9 stable 版本详解INSERT 去重性能回归修复、cgroupv2 内存追踪改进与关键 Bug 修复 本篇基于数据库OLAP列式数据库大数据实时分析数据分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表