NumPy 2.1.0 发布说明#

NumPy 2.1.0 支持即将发布的 Python 3.13 版本,并取消了对 Python 3.9 的支持。除了常规的 bug 修复和更新的 Python 支持外,它还有助于我们在 2.0 版本长期开发后恢复正常的发布周期。此版本的亮点包括:

  • 支持 array-api 2023.12 标准。

  • 支持 Python 3.13。

  • 初步支持自由线程 Python 3.13。

此版本支持 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)

已过期弃用#

  • 对于 numpy.nonzeronumpy.ndarray.nonzero,不允许使用标量和 0D 数组。

    (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)

新特性#

初步支持自由线程 CPython 3.13#

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

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

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

对象数组尤其需要特殊处理,因为 GIL 以前为对象数组访问提供了锁定,但现在不再提供。有关自由线程构建中对象数组的更多信息,请参阅 问题 #27199

如果您对自由线程 Python 感兴趣,例如因为您有一个基于多进程的工作流,并且您希望使用 Python 线程运行它,我们鼓励您进行测试和实验。

如果您遇到您怀疑是 NumPy 引起的问题,请提交问题,首先检查该 bug 是否也出现在“常规”非自由线程 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.printoptionsnumpy.get_printoptionsnumpy.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 可以生成与自由线程兼容的 C 扩展#

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

(gh-26981)

改进#

histogram 自动分箱现在对整数输入数据返回 >=1 的箱尺寸#

对于整数输入数据,小于 1 的箱尺寸会导致虚假的空箱。现在,当使用 histogram_bin_edges 提供的算法之一计算箱数时,可以避免这种情况。

(gh-12150)

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

ndarray 的静态类型化是一项长期努力,此更改是其中的一部分。它是一种带有形状和数据类型参数的泛型类型。以前,形状类型参数可以是任何值。此更改将其限制为整数元组,正如使用 ndarray.shape 所期望的那样。此外,形状类型参数已从不变式更改为协变式。此更改也适用于 ndarray 的子类型,例如 numpy.ma.MaskedArray。有关更多信息,请参阅类型化文档

(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 的先前版本中,打印选项是使用 Python 和 C 全局变量的组合定义的。我们已进行重构,将状态存储在 Python ContextVar 中,使上下文管理器成为线程和异步安全的。

(gh-26846)

类型提示 numpy.polynomial#

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

(gh-26897)

改进的 numpy.dtypes 类型提示#

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

(gh-27008)

性能改进和变更#

  • numpy.save 现在使用 pickle 协议版本 4 来保存对象 dtype 的数组,这允许 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.floornumpy.ceilnumpy.trunc 现在不会对整数和布尔 dtype 输入数组执行转换为浮点 dtype 的操作。

    (gh-26766)

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

ma.corrcoef 目前使用成对观测方法来计算每对变量的标准差。这一做法已更改,因为它被用于标准化协方差,而该协方差是使用 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 维数组)时只使用 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)