news 2026/9/20 13:00:42

NumPy 2.1.0 新特性解析:Python 3.13 自由线程支持、unstack 与 API 兼容性变化全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NumPy 2.1.0 新特性解析:Python 3.13 自由线程支持、unstack 与 API 兼容性变化全指南

NumPy 2.1.0 新特性解析:Python 3.13 自由线程支持、unstack 与 API 兼容性变化全指南

【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy

NumPy 2.1.0 是 2.0 大规模重构之后的回归常规节奏版本,核心亮点是为即将到来的 Python 3.13 提供支持、初步支持自由线程(free-threaded)CPython,以及对 array-api 2023.12 标准的适配。本指南以官方发布说明(doc/source/release/2.1.0-notes.rst)为主线,结合仓库源码逐项解读新函数、弃用项、C API 变更与性能改进,帮助你在升级迁移时准确评估影响面。

读完本文你将掌握:如何使用新的np.unstackoverride_reprcumulative_sum/cumulative_prod等新 API;自由线程 Python 3.13 下 NumPy 的使用边界与 f2py 扩展的适配方法;以及copytoclipquantile等行为变化对既有代码的潜在影响。

版本总览与支持范围

NumPy 2.1.0 的主要发布目标有三个:

  • 支持即将发布的 Python 3.13,并放弃对 Python 3.9 的支持
  • 初步支持自由线程(free-threaded)的 CPython 3.13;
  • 支持 array-api 2023.12 标准。

本版本支持的 Python 版本范围为3.10–3.13。升级到 2.1.0 之前,请先确认你的运行环境满足这一 Python 版本约束。

新函数 numpy.unstack

np.unstack(array, axis=...)是 2.1.0 新增的数组拆分函数,用于沿指定轴将一个数组拆分为多个数组组成的元组(tuple),功能上作为 numpy.stack 的逆操作:

stack(unstack(x, axis=axis), axis=axis) == x

其核心实现位于 numpy/_core/shape_base.py#L470-L519,通过array_function_dispatch派发,实现上等价于tuple(np.moveaxis(x, axis, 0))——因为对数组的迭代总是沿第一个轴进行。

import numpy as np arr = np.arange(24).reshape((2, 3, 4)) # 默认 axis=0,沿第一维拆成 2 个形状为 (3, 4) 的数组 np.unstack(arr) # (array([[ 0, 1, 2, 3], # [ 4, 5, 6, 7], # [ 8, 9, 10, 11]]), # array([[12, 13, 14, 15], # [16, 17, 18, 19], # [20, 21, 22, 23]])) np.unstack(arr, axis=1) # 沿第二维拆分 np.unstack(arr, axis=-1) # 沿最后一维拆分,与 axis=2 等价

注意该函数的签名是位置参数x配合关键字axis(默认0),axis不支持负值以外的非常规语义,负索引与 Python 切片约定一致。

弃用项(Deprecations)

numpy.save 的 fix_imports 参数弃用

自 NumPy 1.17 起,numpy.save已改用不再支持 Python 2 的 pickle 协议,fix_imports关键字参数实际上一直处于被忽略状态,仅为向后兼容而保留。2.1.0 起该参数正式标记为弃用。如果你的代码中仍显式传入fix_imports,升级后应将其删除。

bincount 首个参数禁止传入非整数

将非整数输入作为numpy.bincount的第一个参数现已弃用。此前这类输入会被静默强制转换为整数,可能造成精度丢失而没有任何警告。从 2.1.0 开始这一行为被正式弃用,请在调用前自行完成显式转换(如np.bincount(arr.astype(np.intp)))。

过期弃用(Expired Deprecations)

以下在早期版本中已发出弃用警告的特性,在 2.1.0 中被正式移除或收紧:

  • 标量与 0 维数组禁止用于numpy.nonzeronumpy.ndarray.nonzero:此前对 0 维输入的行为含糊,现在直接报错;
  • set_string_function内部函数被移除,对应的 C 函数PyArray_SetStringFunction被 stub 化(仅保留符号、不再可用)。

C API 变更:链接行为与扩展兼容性

API 符号默认隐藏但可自定义

NumPy 2.1.0 默认隐藏其导出的 API 符号,这意味着默认情况下无法再从其他库动态获取 NumPy API(Windows 上此前也从未支持过)。若你的代码出现与PyArray_APIPyArray_RUNTIME_VERSION相关的链接错误,可通过定义宏NPY_API_SYMBOL_ATTRIBUTE选择退出这一变更。

若问题源于某个上游头文件先包含了 NumPy 头文件,标准解法是:在包含该上游头文件之前先#include "numpy/ndarrayobject.h",并参照仓库中的 C API 使用文档自行导入 NumPy。

npy_3kcompat.h 中大量 shim 被移除

npy_3kcompat.h中大量面向旧版 Python 3 的兼容层与辅助函数被删除。若你的扩展代码依赖其中某个 shim,最稳妥的做法是将旧版该头文件直接 vendoring 进你的代码库。

PyUFuncObject 新增 process_core_dims_func 字段

对广义 ufunc(generalized ufunc)作者而言,这是重要增强:结构体PyUFuncObject新增字段process_core_dims_func,可设置为类型为PyUFunc_ProcessCoreDimsFunc的函数。该函数会在 ufunc 被调用时触发,允许 ufunc 作者:

  • 校验 core 维度是否满足额外约束;
  • 在用户未提供输出 core 维度大小时,为其设置输出维度。

这为自定义 gufunc 的维度检查与推断提供了官方扩展点。

新特性详解

初步支持自由线程 CPython 3.13

PEP 703 提出的 free-threaded CPython 3.13(实验性构建)移除了 GIL。NumPy 2.1 对该构建提供初步支持,为此修复了大量 C 层线程安全问题:此前 NumPy 使用大量 C 全局静态变量存储运行时缓存与状态,2.1 通过三种方式处理——重构以避免全局状态、将全局状态改为线程局部(thread-local)状态、或为共享状态加锁。

必须明确的边界:支持自由线程 Python 并不等于 NumPy 线程安全。

  • 对 ndarray 的只读共享访问是安全的;
  • NumPy 暴露共享可变状态,且没有为数组对象本身加锁来串行化对共享状态的访问;
  • 在多线程中同时修改同一数组(例如同时调用 ufunc 与resize方法)确实可能使 NumPy 崩溃。官方指引现阶段是"不要这样做";
  • 对象数组(object arrays)需要特别注意:GIL 此前为对象数组访问提供了隐式锁,自由线程构建中不再有这一保护(相关讨论见 Issue #27199)。

建议:如果你有基于 multiprocessing 的工作流想迁移到线程,可以积极测试,但遇到可疑问题时应先确认在常规(非自由线程)CPython 3.13 构建下是否同样复现——许多线程 bug 在释放 GIL 的代码中也会出现,禁用 GIL 只是让这类问题更容易暴露。

reshape 支持 shape 与 copy 参数

numpy.reshapenumpy.ndarray.reshape新增shapecopy关键字参数。此前reshape只有在必要时才复制数据,现在可以通过copy=True/False显式控制复制语义,与 NumPy 2.0 起统一的关键字风格保持一致。

DLPack v1 支持

NumPy 现在支持 DLPack v1 协议,旧版本协议的支持将在未来弃用。DLPack 是跨框架共享张量内存的标准协议,这一升级让 NumPy 与 PyTorch、JAX 等生态的零拷贝互操作保持在最新标准之上。

asanyarray 支持 copy 与 device 参数

numpy.asanyarray新增copydevice参数,与numpy.asarray对齐。device参数用于指定目标设备(默认 CPU),是 NumPy 迈向多设备互操作(array-api 标准)的一部分。

打印选项新增 override_repr

numpy.printoptionsnumpy.get_printoptionsnumpy.set_printoptions新增override_repr选项,用于自定义repr(array)行为。在 numpy/_core/arrayprint.py#L1601-L1608 中可以看到实现:当override_repr被设置时,_array_repr_implementation会直接返回override_repr(arr)的结果,忽略其他所有打印选项

import numpy as np def my_repr(arr): return f"<Array shape={arr.shape} sum={arr.sum()}>" with np.printoptions(override_repr=my_repr): print(np.arange(6).reshape(2, 3)) # <Array shape=(2, 3) sum=15>

注意:override_reprformatter一样,在每次调用set_printoptions时都会被重置(见 numpy/_core/arrayprint.py#L318-L324)。该选项只影响 ndarray 的 repr,不影响标量。

cumulative_sum 与 cumulative_prod:array-api 兼容的累加/累乘

新增numpy.cumulative_sumnumpy.cumulative_prod,作为numpy.cumsum/numpy.cumprod的 array-api 兼容替代(实现位于 numpy/_core/fromnumeric.py)。新函数的核心差异是支持固定初始值(include_initial)sum的初始值为 0,prod的初始值为 1,可将初始值包含在返回序列中,便于对齐累积语义。

clip 支持 max/min 关键字

numpy.clip新增maxmin关键字参数,用于取代旧的a_mina_max(旧参数仍可用,但新名更符合 NumPy 2 的命名风格)。同时行为修正:np.clip(a)np.clip(a, None, None)现在返回输入数组的副本,而不再抛错。

astype 支持 device 参数

numpy.astype新增device参数,配合asanyarray/asarraydevice参数,完善了跨设备类型转换的基础设施。

f2py 生成自由线程兼容扩展

f2py CLI 工具新增--freethreading-compatible标志(命令行解析位于 numpy/f2py/f2py2e.py#L108-L113 与 #L553):

python -m numpy.f2py -c --freethreading-compatible mymod.f90 -m mymod

该标志生成的 C 扩展会被标记为与自由线程 CPython 解释器兼容,从而阻止解释器在导入该扩展时于运行时重新启用 GIL。注意:f2py不会分析 Fortran 代码的线程安全性,标记为兼容之前你必须自行确认被包装的 Fortran 代码在并发环境下是安全的。

改进(Improvements)

histogram 整数输入的自动分箱修正

对整数输入数据,当使用histogram_bin_edges提供的算法自动计算 bin 数量时,若计算出的 bin 宽度小于 1,会产生虚假的空 bin。2.1.0 修正了这一点:整数数据自动分箱现在保证 bin 大小不小于 1。

ndarray 形状类型参数协变且约束为 tuple[int, ...]

静态类型体系持续演进:ndarray的形状类型参数(shape type parameter)此前可以是任意值,现在被限制为tuple[int, ...],与ndarray.shape的运行时语义一致;同时该参数从不变(invariant)改为协变(covariant)。此变更同样适用于ndarray的子类型,如numpy.ma.MaskedArray。这会在类型检查(如 mypy、pyright)层面对使用泛型 ndarray 的代码产生更精确的推导,但协变放宽也可能暴露此前被掩盖的类型错误。

quantile 的 closest_observation 方法取最近偶数阶统计量

np.quantile(..., method="closest_observation")在边界情况下的"最近"定义从最近奇数阶统计量改为最近偶数阶统计量,与其它参考实现保持一致。如果你用该方法做过精确数值比对,升级后应对结果做一次回归验证。

lapack_lite 线程安全

lapack_lite是 NumPy 在构建时未检测到系统 BLAS/LAPACK 时使用的内置极简低性能 LAPACK 实现。此前它不是线程安全的:单线程使用无碍,但多线程并发执行线性代数操作可能因数据竞争导致错误结果甚至段错误。2.1.0 为lapack_lite添加了全局锁,串行化多线程下的访问,消除了这部分数据竞争。

printoptions 上下文管理器线程与异步安全

此前 printoptions 状态由 Python 与 C 全局变量混合存储。2.1.0 将其重构为存储在 PythonContextVar中——底层实现在 numpy/_core/printoptions.py#L14-L32,可以看到format_options = ContextVar("format_options", default=default_format_options_dict)。这使得printoptions上下文管理器在多线程与 asyncio 异步场景下都是安全的,不同协程/线程可以拥有各自独立的打印选项状态。

numpy.polynomial 类型注解

自 2.1.0 起,numpy.polynomial及其子包(chebyshev、hermite、laguerre、legendre、polynomial 等)的函数与便捷类均引入了 PEP 484 类型注解,类型检查器可以更可靠地验证多项式代码。

numpy.dtypes 类型提示改进

numpy.dtypes的类型注解更贴近运行时行为:原来使用的numpy.dtype类型别名被替换为专门的 dtype 子类型,并补齐了此前缺失的numpy.dtypes.StringDType注解。

性能改进

numpy.save 使用 pickle protocol 4

numpy.save保存 object dtype 数组时改用pickle protocol 4:支持超过 4GB 的 pickle 对象,且大型数组的保存速度提升约 5%。

OpenBLAS 构建调整(x86_64/i686 与 Windows)

  • x86_64 与 i686 平台上的 OpenBLAS 使用更少的内核(kernels)构建,基于基准测试收敛为 5 个性能簇:PRESCOTT NEHALEM SANDYBRIDGE HASWELL SKYLAKEX,缩小二进制体积的同时覆盖主流微架构;
  • Windows 上的 OpenBLAS 不再链接 quadmath,简化了许可合规;
  • 因 Windows 上 OpenBLAS 的回归,OpenBLAS 0.3.26 多线程带来的性能提升被回退。

ma.cov 与 ma.corrcoef 显著加速

ma.covma.corrcoef及其内部私有函数被重构,在大规模 masked arrays 上显著提速。但注意伴随的行为变化(见下文"Changes"),速度提升以轻微的结果差异为代价。

行为变化(Changes)

vecdot 成为 ufunc 后签名精度降低

numpy.vecdot现在是一个 ufunc,受 ufunc 类型桩(typing stub)限制,其类型签名不如此前精确。

floor/ceil/trunc 不再对整数输入做浮点转换

numpy.floornumpy.ceilnumpy.trunc对整数与布尔 dtype 的输入数组不再执行到浮点 dtype 的转换——此前np.floor(np.arange(3))会返回 float 数组,2.1.0 起保持整数 dtype,结果语义更直观且避免不必要的类型提升。

ma.corrcoef 可能返回略有不同的结果

ma.corrcoef此前对每对变量使用逐对(pairwise)观测计算标准差,用于归一化由ma.cov估计的协方差——但ma.cov本身并不逐对处理观测,这种归一化并不必要。2.1.0 改用每个变量各自的标准差归一化:

  • 显著减少墙钟时间(wall time);
  • 当一对变量的观测不完全对齐时,相关系数估计会与旧版略有不同
  • 其余场景结果不变,包括无掩码值时与corrcoef返回相同的相关矩阵

如果你依赖ma.corrcoef的精确数值(如测试断言),建议核对新旧结果。

copyto 与 full 的转换安全性修正(NEP 50)

copyto现在正确遵循 NEP 50 并应用其转换安全性规则。Python 整数到 NumPy 整数、Python float 到 NumPy float 的转换现在即使可能赋值失败或精度丢失,也被视为"safe"。具体变化:

import numpy as np # 1) 此前是 unsafe/same-kind 转换,现在总是抛错; # 若确实需要 unsafe 转换,请传入数组或 NumPy 标量 np.copyto(np.zeros(3, np.int8), 1000) # 现在总是 raise # 2) safe 转换下由 TypeError 变为 OverflowError np.copyto(np.zeros(3, np.uint8), 1000, casting="safe") # 现在抛出 OverflowError(此前因 same-kind 抛 TypeError) # 3) 溢出行为变化:float32 装不下 1e300,safe 转换下溢出为 inf np.copyto(np.zeros(3, np.float32), 1e300, casting="safe") # 现在得到 inf(此前抛 TypeError) # 4) 仅使用 dtype 判断:NumPy 标量不再"看值"判断 np.copyto(np.zeros(3, np.float32), np.float64(3.0), casting="safe") # raise np.copyto(np.zeros(3, np.int8), np.int64(100), casting="safe") # raise

最后两条是关键语义变化:旧版会检查100是否能放入int8数组,新规则只看 dtype 转换关系,因此 NumPy 标量(或 0 维数组)赋值在 safe 模式下更严格。这一改动让copytofullfull_like与 NumPy 2 的完整行为对齐。升级后应重点检查依赖 safe casting 的数值流水线代码。

升级建议小结

  1. Python 版本:确认运行在 3.10–3.13,尽早规划离开 3.9;
  2. 编译型扩展:检查是否依赖被隐藏的 API 符号(必要时定义NPY_API_SYMBOL_ATTRIBUTE)、npy_3kcompat.h中的旧 shim、以及PyUFuncObject的新字段扩展点;
  3. 数值行为:重点回归copyto/full的 casting 规则、ma.corrcoef的归一化变化、quantile(closest_observation)的取整变化、floor/ceil/trunc的 dtype 保持;
  4. 新 API 采纳unstackoverride_reprcumulative_sum/cumulative_prodreshape(copy=...)等新能力可直接提升代码简洁度与可读性;
  5. 自由线程 Python:若计划使用,先明确只读共享安全、可变共享需自行加锁的边界,并对 object arrays 额外小心。

【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 12:59:20

DeskcommCRM实战:桌面通信型客户关系管理系统的设计与落地

1. 这个项目到底解决什么问题先说结论&#xff1a;DeskcommCRM 不是一个花哨的客户管理玩具&#xff0c;而是一套以“桌面办公 即时通信协同”为核心的客户关系管理方案。换句话说&#xff0c;它解决的是那些每天坐在电脑前、靠消息和邮件跟客户打交道的团队最头痛的问题——客…

作者头像 李华
网站建设 2026/9/20 12:58:09

AI编码预算失控:如何像治理云账单一样管好Token成本

年后回来复工的第一天&#xff0c;我打开上个月的云账单汇总&#xff0c;发现除了熟悉的计算、存储、网络费用之外&#xff0c;多了一行让人又爱又恨的支出&#xff1a;AI编程助手。金额不是特别夸张&#xff0c;但它比上个月涨了将近三成&#xff0c;这个涨幅甚至超过了我们核…

作者头像 李华
网站建设 2026/9/20 12:56:42

半年报拆解实战:科技公司财务指标与经营分析全流程

简介&#xff1a;这是一份郑州畅想高科股份有限公司&#xff08;NEEQ:430547&#xff09;2019年半年度报告&#xff0c;面向投资者、行业研究员及关注新三板铁路信息化领域的财经学生。报告完整披露了公司报告期内的经营数据、财务指标、管理层讨论、重要事项及股本变动情况&am…

作者头像 李华
网站建设 2026/9/20 12:55:32

MMPose 133关键点全身姿态估计三步快速跑通

MMPose 133关键点全身姿态估计三步快速跑通 【免费下载链接】mmpose OpenMMLab Pose Estimation Toolbox and Benchmark. 项目地址: https://gitcode.com/GitHub_Trending/mm/mmpose 做健身动作纠正时&#xff0c;只拿到身体的 17 个关节远远不够&#xff0c;手指和面部…

作者头像 李华
网站建设 2026/9/20 12:55:25

信号与系统前三章复习:抓住傅里叶变换与卷积等核心考点

简介&#xff1a;围绕《信号与系统》前三章的复习资料&#xff0c;面向电子工程、通信类专业学生&#xff0c;用于系统梳理信号时域分析的核心概念。信号与系统是电子与通信领域的重要基础课&#xff0c;前三章涉及的信号分类、分解与变换&#xff0c;是后续频域分析的重要基石…

作者头像 李华