ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

NumPy 2.1.0 新特性解析:Python 3.13 自由线程支持、unstack 与 API 兼容性变化全指南

NumPy 2.1.0 新特性解析:Python 3.13 自由线程支持、unstack 与 API 兼容性变化全指南 NumPy 2.1.0 新特性解析Python 3.13 自由线程支持、unstack 与 API 兼容性变化全指南【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpyNumPy 2.1.0 是 2.0 大规模重构之后的回归常规节奏版本核心亮点是为即将到来的 Python 3.13 提供支持、初步支持自由线程free-threadedCPython以及对 array-api 2023.12 标准的适配。本指南以官方发布说明doc/source/release/2.1.0-notes.rst为主线结合仓库源码逐项解读新函数、弃用项、C API 变更与性能改进帮助你在升级迁移时准确评估影响面。读完本文你将掌握如何使用新的np.unstack、override_repr、cumulative_sum/cumulative_prod等新 API自由线程 Python 3.13 下 NumPy 的使用边界与 f2py 扩展的适配方法以及copyto、clip、quantile等行为变化对既有代码的潜在影响。版本总览与支持范围NumPy 2.1.0 的主要发布目标有三个支持即将发布的 Python 3.13并放弃对 Python 3.9 的支持初步支持自由线程free-threaded的 CPython 3.13支持 array-api 2023.12 标准。本版本支持的 Python 版本范围为3.10–3.13。升级到 2.1.0 之前请先确认你的运行环境满足这一 Python 版本约束。新函数 numpy.unstacknp.unstack(array, axis...)是 2.1.0 新增的数组拆分函数用于沿指定轴将一个数组拆分为多个数组组成的元组tuple功能上作为 numpy.stack 的逆操作stack(unstack(x, axisaxis), axisaxis) x其核心实现位于 numpy/_core/shape_base.py#L470-L519通过array_function_dispatch派发实现上等价于tuple(np.moveaxis(x, axis, 0))——因为对数组的迭代总是沿第一个轴进行。import numpy as np arr np.arange(24).reshape((2, 3, 4)) # 默认 axis0沿第一维拆成 2 个形状为 (3, 4) 的数组 np.unstack(arr) # (array([[ 0, 1, 2, 3], # [ 4, 5, 6, 7], # [ 8, 9, 10, 11]]), # array([[12, 13, 14, 15], # [16, 17, 18, 19], # [20, 21, 22, 23]])) np.unstack(arr, axis1) # 沿第二维拆分 np.unstack(arr, axis-1) # 沿最后一维拆分与 axis2 等价注意该函数的签名是位置参数x配合关键字axis默认0axis不支持负值以外的非常规语义负索引与 Python 切片约定一致。弃用项Deprecationsnumpy.save 的 fix_imports 参数弃用自 NumPy 1.17 起numpy.save已改用不再支持 Python 2 的 pickle 协议fix_imports关键字参数实际上一直处于被忽略状态仅为向后兼容而保留。2.1.0 起该参数正式标记为弃用。如果你的代码中仍显式传入fix_imports升级后应将其删除。bincount 首个参数禁止传入非整数将非整数输入作为numpy.bincount的第一个参数现已弃用。此前这类输入会被静默强制转换为整数可能造成精度丢失而没有任何警告。从 2.1.0 开始这一行为被正式弃用请在调用前自行完成显式转换如np.bincount(arr.astype(np.intp))。过期弃用Expired Deprecations以下在早期版本中已发出弃用警告的特性在 2.1.0 中被正式移除或收紧标量与 0 维数组禁止用于numpy.nonzero和numpy.ndarray.nonzero此前对 0 维输入的行为含糊现在直接报错set_string_function内部函数被移除对应的 C 函数PyArray_SetStringFunction被 stub 化仅保留符号、不再可用。C API 变更链接行为与扩展兼容性API 符号默认隐藏但可自定义NumPy 2.1.0 默认隐藏其导出的 API 符号这意味着默认情况下无法再从其他库动态获取 NumPy APIWindows 上此前也从未支持过。若你的代码出现与PyArray_API或PyArray_RUNTIME_VERSION相关的链接错误可通过定义宏NPY_API_SYMBOL_ATTRIBUTE选择退出这一变更。若问题源于某个上游头文件先包含了 NumPy 头文件标准解法是在包含该上游头文件之前先#include numpy/ndarrayobject.h并参照仓库中的 C API 使用文档自行导入 NumPy。npy_3kcompat.h 中大量 shim 被移除npy_3kcompat.h中大量面向旧版 Python 3 的兼容层与辅助函数被删除。若你的扩展代码依赖其中某个 shim最稳妥的做法是将旧版该头文件直接 vendoring 进你的代码库。PyUFuncObject 新增 process_core_dims_func 字段对广义 ufuncgeneralized ufunc作者而言这是重要增强结构体PyUFuncObject新增字段process_core_dims_func可设置为类型为PyUFunc_ProcessCoreDimsFunc的函数。该函数会在 ufunc 被调用时触发允许 ufunc 作者校验 core 维度是否满足额外约束在用户未提供输出 core 维度大小时为其设置输出维度。这为自定义 gufunc 的维度检查与推断提供了官方扩展点。新特性详解初步支持自由线程 CPython 3.13PEP 703 提出的 free-threaded CPython 3.13实验性构建移除了 GIL。NumPy 2.1 对该构建提供初步支持为此修复了大量 C 层线程安全问题此前 NumPy 使用大量 C 全局静态变量存储运行时缓存与状态2.1 通过三种方式处理——重构以避免全局状态、将全局状态改为线程局部thread-local状态、或为共享状态加锁。必须明确的边界支持自由线程 Python 并不等于 NumPy 线程安全。对 ndarray 的只读共享访问是安全的NumPy 暴露共享可变状态且没有为数组对象本身加锁来串行化对共享状态的访问在多线程中同时修改同一数组例如同时调用 ufunc 与resize方法确实可能使 NumPy 崩溃。官方指引现阶段是不要这样做对象数组object arrays需要特别注意GIL 此前为对象数组访问提供了隐式锁自由线程构建中不再有这一保护相关讨论见 Issue #27199。建议如果你有基于 multiprocessing 的工作流想迁移到线程可以积极测试但遇到可疑问题时应先确认在常规非自由线程CPython 3.13 构建下是否同样复现——许多线程 bug 在释放 GIL 的代码中也会出现禁用 GIL 只是让这类问题更容易暴露。reshape 支持 shape 与 copy 参数numpy.reshape与numpy.ndarray.reshape新增shape与copy关键字参数。此前reshape只有在必要时才复制数据现在可以通过copyTrue/False显式控制复制语义与 NumPy 2.0 起统一的关键字风格保持一致。DLPack v1 支持NumPy 现在支持 DLPack v1 协议旧版本协议的支持将在未来弃用。DLPack 是跨框架共享张量内存的标准协议这一升级让 NumPy 与 PyTorch、JAX 等生态的零拷贝互操作保持在最新标准之上。asanyarray 支持 copy 与 device 参数numpy.asanyarray新增copy与device参数与numpy.asarray对齐。device参数用于指定目标设备默认 CPU是 NumPy 迈向多设备互操作array-api 标准的一部分。打印选项新增 override_reprnumpy.printoptions、numpy.get_printoptions、numpy.set_printoptions新增override_repr选项用于自定义repr(array)行为。在 numpy/_core/arrayprint.py#L1601-L1608 中可以看到实现当override_repr被设置时_array_repr_implementation会直接返回override_repr(arr)的结果忽略其他所有打印选项。import numpy as np def my_repr(arr): return fArray shape{arr.shape} sum{arr.sum()} with np.printoptions(override_reprmy_repr): print(np.arange(6).reshape(2, 3)) # Array shape(2, 3) sum15注意override_repr与formatter一样在每次调用set_printoptions时都会被重置见 numpy/_core/arrayprint.py#L318-L324。该选项只影响 ndarray 的 repr不影响标量。cumulative_sum 与 cumulative_prodarray-api 兼容的累加/累乘新增numpy.cumulative_sum和numpy.cumulative_prod作为numpy.cumsum/numpy.cumprod的 array-api 兼容替代实现位于 numpy/_core/fromnumeric.py。新函数的核心差异是支持固定初始值include_initialsum的初始值为 0prod的初始值为 1可将初始值包含在返回序列中便于对齐累积语义。clip 支持 max/min 关键字numpy.clip新增max与min关键字参数用于取代旧的a_min与a_max旧参数仍可用但新名更符合 NumPy 2 的命名风格。同时行为修正np.clip(a)或np.clip(a, None, None)现在返回输入数组的副本而不再抛错。astype 支持 device 参数numpy.astype新增device参数配合asanyarray/asarray的device参数完善了跨设备类型转换的基础设施。f2py 生成自由线程兼容扩展f2py CLI 工具新增--freethreading-compatible标志命令行解析位于 numpy/f2py/f2py2e.py#L108-L113 与 #L553python -m numpy.f2py -c --freethreading-compatible mymod.f90 -m mymod该标志生成的 C 扩展会被标记为与自由线程 CPython 解释器兼容从而阻止解释器在导入该扩展时于运行时重新启用 GIL。注意f2py不会分析 Fortran 代码的线程安全性标记为兼容之前你必须自行确认被包装的 Fortran 代码在并发环境下是安全的。改进Improvementshistogram 整数输入的自动分箱修正对整数输入数据当使用histogram_bin_edges提供的算法自动计算 bin 数量时若计算出的 bin 宽度小于 1会产生虚假的空 bin。2.1.0 修正了这一点整数数据自动分箱现在保证 bin 大小不小于 1。ndarray 形状类型参数协变且约束为 tuple[int, ...]静态类型体系持续演进ndarray的形状类型参数shape type parameter此前可以是任意值现在被限制为tuple[int, ...]与ndarray.shape的运行时语义一致同时该参数从不变invariant改为协变covariant。此变更同样适用于ndarray的子类型如numpy.ma.MaskedArray。这会在类型检查如 mypy、pyright层面对使用泛型 ndarray 的代码产生更精确的推导但协变放宽也可能暴露此前被掩盖的类型错误。quantile 的 closest_observation 方法取最近偶数阶统计量np.quantile(..., methodclosest_observation)在边界情况下的最近定义从最近奇数阶统计量改为最近偶数阶统计量与其它参考实现保持一致。如果你用该方法做过精确数值比对升级后应对结果做一次回归验证。lapack_lite 线程安全lapack_lite是 NumPy 在构建时未检测到系统 BLAS/LAPACK 时使用的内置极简低性能 LAPACK 实现。此前它不是线程安全的单线程使用无碍但多线程并发执行线性代数操作可能因数据竞争导致错误结果甚至段错误。2.1.0 为lapack_lite添加了全局锁串行化多线程下的访问消除了这部分数据竞争。printoptions 上下文管理器线程与异步安全此前 printoptions 状态由 Python 与 C 全局变量混合存储。2.1.0 将其重构为存储在 PythonContextVar中——底层实现在 numpy/_core/printoptions.py#L14-L32可以看到format_options ContextVar(format_options, defaultdefault_format_options_dict)。这使得printoptions上下文管理器在多线程与 asyncio 异步场景下都是安全的不同协程/线程可以拥有各自独立的打印选项状态。numpy.polynomial 类型注解自 2.1.0 起numpy.polynomial及其子包chebyshev、hermite、laguerre、legendre、polynomial 等的函数与便捷类均引入了 PEP 484 类型注解类型检查器可以更可靠地验证多项式代码。numpy.dtypes 类型提示改进numpy.dtypes的类型注解更贴近运行时行为原来使用的numpy.dtype类型别名被替换为专门的 dtype 子类型并补齐了此前缺失的numpy.dtypes.StringDType注解。性能改进numpy.save 使用 pickle protocol 4numpy.save保存 object dtype 数组时改用pickle protocol 4支持超过 4GB 的 pickle 对象且大型数组的保存速度提升约 5%。OpenBLAS 构建调整x86_64/i686 与 Windowsx86_64 与 i686 平台上的 OpenBLAS 使用更少的内核kernels构建基于基准测试收敛为 5 个性能簇PRESCOTT NEHALEM SANDYBRIDGE HASWELL SKYLAKEX缩小二进制体积的同时覆盖主流微架构Windows 上的 OpenBLAS 不再链接 quadmath简化了许可合规因 Windows 上 OpenBLAS 的回归OpenBLAS 0.3.26 多线程带来的性能提升被回退。ma.cov 与 ma.corrcoef 显著加速ma.cov与ma.corrcoef及其内部私有函数被重构在大规模 masked arrays 上显著提速。但注意伴随的行为变化见下文Changes速度提升以轻微的结果差异为代价。行为变化Changesvecdot 成为 ufunc 后签名精度降低numpy.vecdot现在是一个 ufunc受 ufunc 类型桩typing stub限制其类型签名不如此前精确。floor/ceil/trunc 不再对整数输入做浮点转换numpy.floor、numpy.ceil、numpy.trunc对整数与布尔 dtype 的输入数组不再执行到浮点 dtype 的转换——此前np.floor(np.arange(3))会返回 float 数组2.1.0 起保持整数 dtype结果语义更直观且避免不必要的类型提升。ma.corrcoef 可能返回略有不同的结果ma.corrcoef此前对每对变量使用逐对pairwise观测计算标准差用于归一化由ma.cov估计的协方差——但ma.cov本身并不逐对处理观测这种归一化并不必要。2.1.0 改用每个变量各自的标准差归一化显著减少墙钟时间wall time当一对变量的观测不完全对齐时相关系数估计会与旧版略有不同其余场景结果不变包括无掩码值时与corrcoef返回相同的相关矩阵。如果你依赖ma.corrcoef的精确数值如测试断言建议核对新旧结果。copyto 与 full 的转换安全性修正NEP 50copyto现在正确遵循 NEP 50 并应用其转换安全性规则。Python 整数到 NumPy 整数、Python float 到 NumPy float 的转换现在即使可能赋值失败或精度丢失也被视为safe。具体变化import numpy as np # 1) 此前是 unsafe/same-kind 转换现在总是抛错 # 若确实需要 unsafe 转换请传入数组或 NumPy 标量 np.copyto(np.zeros(3, np.int8), 1000) # 现在总是 raise # 2) safe 转换下由 TypeError 变为 OverflowError np.copyto(np.zeros(3, np.uint8), 1000, castingsafe) # 现在抛出 OverflowError此前因 same-kind 抛 TypeError # 3) 溢出行为变化float32 装不下 1e300safe 转换下溢出为 inf np.copyto(np.zeros(3, np.float32), 1e300, castingsafe) # 现在得到 inf此前抛 TypeError # 4) 仅使用 dtype 判断NumPy 标量不再看值判断 np.copyto(np.zeros(3, np.float32), np.float64(3.0), castingsafe) # raise np.copyto(np.zeros(3, np.int8), np.int64(100), castingsafe) # raise最后两条是关键语义变化旧版会检查100是否能放入int8数组新规则只看 dtype 转换关系因此 NumPy 标量或 0 维数组赋值在 safe 模式下更严格。这一改动让copyto、full、full_like与 NumPy 2 的完整行为对齐。升级后应重点检查依赖 safe casting 的数值流水线代码。升级建议小结Python 版本确认运行在 3.10–3.13尽早规划离开 3.9编译型扩展检查是否依赖被隐藏的 API 符号必要时定义NPY_API_SYMBOL_ATTRIBUTE、npy_3kcompat.h中的旧 shim、以及PyUFuncObject的新字段扩展点数值行为重点回归copyto/full的 casting 规则、ma.corrcoef的归一化变化、quantile(closest_observation)的取整变化、floor/ceil/trunc的 dtype 保持新 API 采纳unstack、override_repr、cumulative_sum/cumulative_prod、reshape(copy...)等新能力可直接提升代码简洁度与可读性自由线程 Python若计划使用先明确只读共享安全、可变共享需自行加锁的边界并对 object arrays 额外小心。【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表