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 现在默认为隐藏它添加的 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#

向结构 PyUFuncObject 添加了字段 process_core_dims_func。对于广义 ufunc,可将此字段设置为类型为 PyUFunc_ProcessCoreDimsFunc 的函数,在调用 ufunc 时将调用此函数。它允许 ufunc 作者检查核心维度是否满足其他约束,并在未提供这些维度时设置输出核心维度大小。

(gh-26908)

新特性#

初步支持免线程 CPython 3.13#

CPython 3.13 将作为实验性免线程版本发布。请参阅 https://py-free-threading.github.ioPEP 703CPython 3.13 版本说明,了解更多关于免线程 Python 的详细信息。

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

支持免线程 Python 并不意味着 NumPy 是线程安全的。对 ndarray 的只读共享访问应该是安全的。NumPy 公开了共享的可变状态,我们没有向数组对象本身添加任何锁定来序列化对共享状态的访问。在用户代码中必须小心,避免在多线程中修改同一个数组时发生竞争。在多线程中同时修改数组肯定可以使 NumPy 崩溃,例如同时调用 ufunc 和 resize 方法。目前我们的指导原则是:“不要这样做”。将来我们希望提供更有力的保证。

对象数组尤其需要特别小心,因为 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可以生成与 freethreading 兼容的 C 扩展#

--freethreading-compatible传递到 f2py CLI 工具,以生成标记为与 free threading 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。有关详细信息,请参阅typing 文档

(gh-26081)

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

这更改了边界案例最近的定义,从最近奇数阶统计量更改为最近偶数阶统计量。Numpy 实现现在匹配其他参考实现。

(gh-26656)

lapack_lite 现在是线程安全的#

NumPy 提供了最小低性能 LAPACK 版本,名为 lapack_lite,可在构建时未检测到任何 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 来保存具有对象数据类型(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)输入数组执行强制转换为浮点数据类型。

    (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") 会引发 TypeError,而不是 OverflowError,原因是同类型转换。

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

此外,仅在指定 NumPy 标量(或 0 维数组)时才使用数据类型,这意味着以下行为不同

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