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)
弃用#
已过期弃用#
C API 变更#
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.io、PEP 703 和 CPython 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.reshape
和numpy.ndarray.reshape
现在支持shape
和copy
参数。(gh-26292)
NumPy 现在支持 DLPack v1,对旧版本的支持将在未来弃用。
(gh-26501)
numpy.asanyarray
现在支持copy
和device
参数,与numpy.asarray
保持一致。(gh-26580)
numpy.printoptions
、numpy.get_printoptions
和numpy.set_printoptions
现在支持一个新选项override_repr
,用于定义自定义的repr(array)
行为。(gh-26611)
新增了
numpy.cumulative_sum
和numpy.cumulative_prod
作为与 Array API 兼容的numpy.cumsum
和numpy.cumprod
替代方案。新函数可以在结果中包含一个固定的初始值(sum
为零,prod
为一)。(gh-26724)
numpy.clip
现在支持max
和min
关键字参数,它们旨在替代a_min
和a_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.cov
和 ma.corrcoef
现在显著加快#
私有函数以及 ma.cov
和 ma.corrcoef
已被重构。它们现在显著加快,尤其是在大型掩码数组上。
(gh-26285)
变更#
由于
numpy.vecdot
现在是一个 ufunc,它的签名精度较低。这是由于 ufunc 类型存根的限制。(gh-26313)
numpy.floor
、numpy.ceil
和numpy.trunc
现在不会对整数和布尔 dtype 输入数组执行转换为浮点 dtype 的操作。(gh-26766)
ma.corrcoef
可能会返回略有不同的结果#
ma.corrcoef
目前使用成对观测方法来计算每对变量的标准差。这一做法已更改,因为它被用于标准化协方差,而该协方差是使用 ma.cov
估计的,后者不以成对方式考虑每个变量的观测值,因此使其变得不必要。标准化已被更合适的每个变量标准差取代,这显著减少了运行时间,但在变量对之间的观测值未对齐的情况下,将返回略有不同的相关系数估计值。然而,在所有其他情况下,它将返回相同的估计值,包括在使用没有掩码值的掩码数组时返回与 corrcoef
相同的相关矩阵。
(gh-26285)
copyto
和 full
中的类型转换安全性修复#
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
。
这使得 copyto
、full
和 full_like
与正确的 NumPy 2 行为保持一致。
(gh-27091)