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)

过时的弃用#

  • numpy.nonzeronumpy.ndarray.nonzero 不允许标量和 0D 数组.

    (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 中.对于广义的 ufuncs,可以将此字段设置为类型为 PyUFunc_ProcessCoreDimsFunc 的函数,当调用 ufunc 时将调用该函数.它允许 ufunc 作者检查核心维度是否满足额外的约束,并在未提供输出核心维度大小时设置它们.

(gh-26908)

新特性#

对自由线程 CPython 3.13 的初步支持#

CPython 3.13 将作为实验性的自由线程构建版提供.请参阅 https://py-free-threading.github.io,`PEP 703 <https://peps.python.org/pep-0703/>`_ 和 CPython 3.13 发布说明 以了解更多关于自由线程 Python 的详细信息.

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

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

特别是对象数组需要特别注意,因为GIL之前为对象数组访问提供了锁定,现在不再提供.有关自由线程构建中的对象数组的更多信息,请参见 Issue #27199.

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

如果你遇到的问题你怀疑是因为NumPy,请 提交一个issue ,首先检查一下这个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 作为与数组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 的 shape-type 参数现在是协变的,并且绑定到 tuple[int, ...]#

ndarray 的静态类型是一个长期的努力,随着这次改变继续进行.它是一个带有形状和数据类型参数的通用类型.以前,形状类型参数可以是任何值.这次改变将其限制为 int 的元组,正如使用 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版本开始,PEP 484类型注解已包含在 numpy.polynomial 及其子包中的函数和便利类中.

(gh-26897)

改进的 numpy.dtypes 类型提示#

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

(gh-27008)

性能提升和变化#

  • numpy.save 现在使用 pickle 协议版本 4 来保存对象类型的数组,这允许保存大于 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.floor, numpy.ceil, 和 numpy.trunc 现在不会对整数和布尔类型输入数组执行浮点类型的转换.

    (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-d 数组)时,仅使用 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)