NumPy 2.1.0 发布说明#

NumPy 2.1.0 支持即将发布的 Python 3.13 版本,并停止支持 Python 3.9。除了常规的错误修复和更新的 Python 支持外,它还有助于我们在 2.0 版本漫长的开发周期后,重新回到正常的发布周期。本次发布的主要亮点包括:

  • 支持 array-api 2023.12 标准。

  • 支持 Python 3.13。

  • 初步支持 Python 3.13 的 free-threaded 版本。

本次发布支持 Python 版本 3.10-3.13。

新增函数#

新函数 numpy.unstack#

添加了一个新函数 np.unstack(array, axis=...),它沿着一个轴将数组拆分成一个元组数组。它是 numpy.stack 的逆操作。

(gh-26579)

弃用#

  • numpy.save 中的 fix_imports 关键字参数已被弃用。自 NumPy 1.17 起,numpy.save 使用的 pickle 协议不再支持 Python 2,并且忽略了 fix_imports 关键字。此关键字仅为向后兼容性而保留。现在已弃用。

    (gh-26452)

  • 将非整数输入作为 bincount 的第一个参数现在已被弃用,因为此类输入会被静默转换为整数,而不会发出精度丢失的警告。

    (gh-27076)

已过期的弃用#

  • 标量和 0D 数组不再允许用于 numpy.nonzeronumpy.ndarray.nonzero

    (gh-26268)

  • 内部函数 set_string_function 已被移除,PyArray_SetStringFunction 已被存根化。

    (gh-26611)

C API 更改#

API 符号现在隐藏但可自定义#

NumPy 现在默认隐藏其添加的 API 符号,以便允许所有 NumPy API 的使用。这意味着默认情况下您无法从其他库动态获取 NumPy API(这在 Windows 上从未可能)。

如果您遇到与 PyArray_APIPyArray_RUNTIME_VERSION 相关的链接错误,您可以定义 NPY_API_SYMBOL_ATTRIBUTE 来选择退出此更改。

如果您因上游头文件包含 NumPy 而遇到问题,解决方案是确保您在包含其头文件之前 #include "numpy/ndarrayobject.h",并根据 including-the-c-api 导入 NumPy。

(gh-26103)

从 npy_3kcompat.h 中移除了许多兼容层#

npy_3kcompat.h 中移除了许多旧的兼容层和辅助函数。如果您发现需要这些,请将文件的先前版本供应商到您的代码库中。

(gh-26842)

PyUFuncObject 新字段 process_core_dims_func#

字段 process_core_dims_func 已添加到结构体 PyUFuncObject 中。对于通用 ufunc,此字段可以设置为一个类型为 PyUFunc_ProcessCoreDimsFunc 的函数,该函数将在调用 ufunc 时被调用。它允许 ufunc 作者检查核心维度是否满足附加约束,以及设置输出核心维度的大小(如果尚未提供)。

(gh-26908)

新功能#

初步支持 Free-Threaded CPython 3.13#

CPython 3.13 将作为实验性的 free-threaded 版本提供。有关 free-threaded Python 的更多详细信息,请参阅 https://py-free-threading.github.ioPEP 703CPython 3.13 发布说明

NumPy 2.1 对 CPython 3.13 的 free-threaded 版本提供了初步支持。此支持通过修复 NumPy 中的多个 C 线程安全问题来实现。在 NumPy 2.1 之前,NumPy 使用大量的 C 全局静态变量来存储运行时缓存和其他状态。我们已对其进行重构以避免全局状态的需要,将全局状态转换为线程局部状态,或添加了锁。

对 free-threaded Python 的支持并不意味着 NumPy 是线程安全的。只读共享访问 ndarray 应该是安全的。NumPy 暴露了共享的可变状态,并且我们没有为数组对象本身添加任何锁来序列化对共享状态的访问。如果您希望在多个线程中修改同一数组,用户代码必须小心避免竞态条件。通过同时在多个线程中修改数组,例如同时调用 ufunc 和 resize 方法,当然有可能导致 NumPy 崩溃。目前我们的建议是:“不要这样做”。将来我们希望提供更强的保证。

特别是对象数组需要特别小心,因为之前的 GIL 曾为对象数组访问提供了锁,而现在不再提供。有关 free-threaded 版本中对象数组的更多信息,请参阅 Issue #27199

如果您对 free-threaded Python 感兴趣,例如因为您有一个基于多进程的工作流,您希望与 Python 线程一起运行,我们鼓励进行测试和实验。

如果您遇到您认为是由 NumPy 引起的问题,请 打开一个 issue,并首先检查该 bug 是否也出现在“常规”非 free-threaded CPython 3.13 版本中。许多线程 bug 也可能出现在释放 GIL 的代码中;禁用 GIL 只会更容易遇到线程 bug。

(gh-26157)

  • numpy.reshapenumpy.ndarray.reshape 现在支持 shapecopy 参数。

    (gh-26292)

  • NumPy 现在支持 DLPack v1,未来将弃用对旧版本的支持。

    (gh-26501)

  • numpy.asanyarray 现在支持 copydevice 参数,与 numpy.asarray 保持一致。

    (gh-26580)

  • numpy.printoptions, numpy.get_printoptions, and numpy.set_printoptions 现在支持一个新的选项 override_repr,用于定义自定义 repr(array) 的行为。

    (gh-26611)

  • 添加了 numpy.cumulative_sumnumpy.cumulative_prod 作为与 Array API 兼容的 numpy.cumsumnumpy.cumprod 的替代方案。新函数可以在结果中包含一个固定的初始值(对于 sum 是零,对于 prod 是一)。

    (gh-26724)

  • numpy.clip 现在支持 maxmin 关键字参数,用于替换 a_mina_max。此外,对于 np.clip(a)np.clip(a, None, None),将返回输入数组的副本而不是引发错误。

    (gh-26724)

  • numpy.astype 现在支持 device 参数。

    (gh-26724)

f2py 可以生成兼容 free-threading 的 C 扩展#

--freethreading-compatible 传递给 f2py CLI 工具,以生成一个标记为与 free threading CPython 解释器兼容的 C 扩展。这样做可以防止解释器在运行时导入 C 扩展时重新启用 GIL。请注意,f2py 不会分析 Fortran 代码的线程安全性,因此在将扩展标记为兼容之前,您必须验证所包装的 Fortran 代码是否线程安全。

(gh-26981)

改进#

histogram 自动分箱现在为整数输入数据返回 bin 大小 >=1#

对于整数输入数据,小于 1 的 bin 大小会导致出现虚假的空 bin。现在,当使用 histogram_bin_edges 提供的算法之一计算 bin 数量时,将避免这种情况。

(gh-12150)

ndarray 的 shape 类型参数现在是协变的,并绑定到 tuple[int, ...]#

ndarray 进行静态类型检查是一项长期的工作,通过此更改仍在继续。它是一个泛型类型,具有形状和数据类型的类型参数。以前,形状类型参数可以是任何值。此更改将其限制为整数元组,正如使用 ndarray.shape 所预期的那样。此外,形状类型参数已从不变性改为协变性。此更改也适用于 ndarray 的子类型,例如 numpy.ma.MaskedArray。有关更多信息,请参阅 typing 文档

(gh-26081)

使用 closest_observation 方法的 np.quantile 选择最近的偶数阶统计量#

这改变了边界情况的“最近”的定义,从最近的奇数阶统计量改为最近的偶数阶统计量。NumPy 实现现在与其他参考实现匹配。

(gh-26656)

lapack_lite 现在是线程安全的#

NumPy 提供了一个名为 lapack_lite 的最小化低性能 LAPACK 版本,如果构建时未检测到任何 BLAS/LAPACK 系统,则可以使用它。

到目前为止,lapack_lite 不是线程安全的。单线程使用场景不会出现任何问题,但在多个线程中运行线性代数运算可能会由于数据竞争而导致错误、不正确的结果或段错误。

我们添加了一个全局锁,以序列化对 lapack_lite 在多个线程中的访问。

(gh-26750)

numpy.printoptions 上下文管理器现在是线程安全和异步安全的#

在 NumPy 的先前版本中,printoptions 是使用 Python 和 C 全局变量的组合定义的。我们对其进行了重构,将状态存储在 Python 的 ContextVar 中,从而使上下文管理器成为线程安全和异步安全的。

(gh-26846)

numpy.polynomial 添加类型提示#

从 2.1 版本开始,PEP 484 类型注解已包含在 numpy.polynomial 及其子包中的函数和方便类中。

(gh-26897)

改进了 numpy.dtypes 类型提示#

numpy.dtypes 的类型注解现在更好地反映了运行时:numpy.dtype 类型别名已被替换为专门的 dtype *子类型*,并且添加了先前缺失的 numpy.dtypes.StringDType 的注解。

(gh-27008)

性能改进和更改#

  • numpy.save 现在对保存具有 object dtypes 的数组使用 pickle 协议版本 4,这允许 pickle 对象大于 4GB,并将大数组的保存速度提高了约 5%。

    (gh-26388)

  • x86_64 和 i686 上的 OpenBLAS 使用更少的内核进行构建。根据基准测试,这些内核周围有 5 个性能集群:PRESCOTT NEHALEM SANDYBRIDGE HASWELL SKYLAKEX

    (gh-27147)

  • Windows 上的 OpenBLAS 在链接时未包含 quadmath,简化了许可。

    (gh-27147)

  • 由于 Windows 上的 OpenBLAS 出现回归,多线程使用 OpenBLAS 0.3.26 时的性能改进已被撤销。

    (gh-27147)

ma.covma.corrcoef 现在速度显著提升#

私有函数已与 ma.covma.corrcoef 一起重构。它们现在速度显著提升,尤其是在大型掩码数组上。

(gh-26285)

更改#

  • 由于 numpy.vecdot 现在是一个 ufunc,其签名精度较低。这是由于 ufunc 的类型存根的限制。

    (gh-26313)

  • numpy.floor, numpy.ceil, and numpy.trunc 现在不会对整数和布尔类型输入数组执行到浮点数据类型的转换。

    (gh-26766)

ma.corrcoef 可能会返回略有不同的结果#

目前在 ma.corrcoef 中使用成对观测方法来计算每对变量的标准差。这一点已得到改变,因为它被用于归一化使用 ma.cov 估计的协方差,而 ma.cov 不考虑成对变量之间的观测值,因此是不必要的。归一化已被更合适地替换为每个变量的标准差,这显著减少了运行时间,但在成对变量之间的观测值不对齐的情况下,将返回相关系数的估计值略有不同。然而,在所有其他情况下,它将返回相同的估计值,包括在使用没有掩码值的掩码数组时返回与 corrcoef 相同的相关矩阵。

(gh-26285)

copytofull 中进行类型安全修复#

copyto 现在正确使用 NEP 50 并将其应用于类型安全。Python 整数到 NumPy 整数的转换以及 Python 浮点数到 NumPy 浮点数的转换现在被认为是“安全”的,即使赋值可能失败或精度可能丢失。这意味着以下示例略有变化:

  • np.copyto(int8_arr, 1000) 以前执行的是不安全的/同类型的转换

    Python 整数。它现在总是会引发错误,要实现不安全的转换,您必须传递一个数组或 NumPy 标量。

  • np.copyto(uint8_arr, 1000, casting="safe") 将引发 OverflowError 而不是 TypeError,因为是同类型转换。

  • np.copyto(float32_arr, 1e300, casting="safe") 将溢出到 inf(float32 无法容纳 1e300),而不是引发 TypeError。

此外,在赋值 NumPy 标量(或 0-d 数组)时仅使用 dtype,这意味着以下行为有所不同:

  • np.copyto(float32_arr, np.float64(3.0), casting="safe") 会引发错误。

  • np.coptyo(int8_arr, np.int64(100), casting="safe") 会引发错误。以前,NumPy 会检查 100 是否适合 int8_arr

这使 copytofullfull_like 与正确的 NumPy 2 行为保持一致。

(gh-27091)