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。

此版本支持 Python 3.10-3.13 版本。

新函数#

新函数 numpy.unstack#

添加了一个新函数 np.unstack(array, axis=...),它沿某个轴将数组拆分为一个数组元组。它是 numpy.stack 的逆运算。

(gh-26579)

弃用功能#

  • numpy.save 中的 fix_imports 关键字参数已弃用。从 NumPy 1.17 开始,numpy.save 使用不再支持 Python 2 的 pickle 协议,并忽略了 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 现在默认隐藏它添加到允许所有 NumPy API 用法的 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 引起的的问题,请 提交问题,首先检查该错误是否也出现在“常规”非多线程 CPython 3.13 版本中。许多线程错误也可能发生在释放 GIL 的代码中;仅禁用 GIL 使得更容易遇到线程错误。

(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 CLI 工具以生成标记为与多线程 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 版本中,printoptions 是使用 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 来保存具有 object dtype 的数组,这允许保存大于 4GB 的 pickle 对象,并使大型数组的保存速度提高约 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 估计),而 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)