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)
弃用功能#
已过期弃用功能#
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 引起的的问题,请 提交问题,首先检查该错误是否也出现在“常规”非多线程 CPython 3.13 版本中。许多线程错误也可能发生在释放 GIL 的代码中;仅禁用 GIL 使得更容易遇到线程错误。
(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 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.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
估计),而 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)