尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

NumPy 1.21.0 版本发布全解析:新随机数生成器、类型系统增强与 ufunc 行为变更指南

NumPy 1.21.0 版本发布全解析:新随机数生成器、类型系统增强与 ufunc 行为变更指南 NumPy 1.21.0 版本发布全解析新随机数生成器、类型系统增强与 ufunc 行为变更指南【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpyNumPy 1.21.0 是一次承前启后的重要发布在延续 SIMD 向量化优化、改进文档与类型注解的同时引入了全新的PCG64DXSM随机数生成器并对通用函数ufunc的dtype/signature语义、数组类型注解等核心机制做了方向性调整。本文基于官方发布说明见 doc/source/release/1.21.0-notes.rst逐项解析新特性、弃用项、兼容性变化与性能改进并结合当前仓库源码给出可直接运行的示例与迁移建议。适用版本与支持范围本发布支持 Python 3.7–3.9Python 3.10 的官方支持在其正式发布后补入。若使用 gcc-11.1 编译注意-O3优化级别可能导致大量错误告警并在某些硬件上出现无限循环挂起问题——这是本版本明确记录的已知问题。一、版本亮点概览本版本的核心亮点集中在五条主线上持续深化 SIMD 优化覆盖更多函数与平台新 dtype 基础设施与类型转换的初期工作为后续 2.x 的 dtype 重构铺路macOS universal2 轮子为 Python 3.8 和 3.9 提供原生双架构x86_64 arm64支持文档与类型注解全面改进包括新增 mypy 插件与可运行时下标化的numpy.typing.NDArray新随机数生成器PCG64DXSM修复了PCG64在大规模并行场景下的统计弱点。除此之外还包含大量常规 Bug 修复与细节改进下文按发布说明的结构逐章展开。二、新函数PCG64DXSM随机数生成器2.1 为什么需要它PCG64BitGenerator 自 NumPy 1.17 引入以来在大规模并行场景下暴露出统计弱点——虽然绝大多数用户永远不会观察到该问题仍可安全继续使用PCG64但官方仍推出了新的PCG64DXSM它将在未来版本中逐步取代PCG64成为default_rng的默认 BitGenerator 实现。PCG64DXSM在不牺牲性能与既有特性的前提下解决了统计弱点。2.2 实现原理源码视角从源码看PCG64DXSM与PCG64共享同一套底层状态结构但采用了更强的输出函数实现见 numpy/random/_pcg64.pyxDXSM 输出函数相比PCG64使用的 XSL RR 输出函数PCG64DXSM使用 PCG CM DXSM 128/64 变体采用更强的 DXSMdouble xor-shift multiply输出函数便宜乘法器cheap multiplierLCG 中使用 64 位 cheap multiplier降低乘法开销先输出后推进从状态推进前的值产生输出而非PCG64的推进后再输出周期与流仍保持2^128周期、支持任意步数推进advance以及2^127条独立流。其初始化入口为PCG64DXSM(seedNone)seed可为None从操作系统取熵、int/整数数组交给SeedSequence派生状态或SeedSequence实例状态向量由两个 128 位无符号整数状态 LCG 增量构成。2.3 使用示例from numpy.random import Generator, PCG64DXSM, SeedSequence rng Generator(PCG64DXSM(1234)) print(rng.standard_normal(5)) # 并行场景为每个子任务派生独立的生成器 sg SeedSequence(1234) rg [Generator(PCG64DXSM(s)) for s in sg.spawn(10)]仓库测试覆盖了PCG64DXSM的种子、状态序列化与流一致性见 numpy/random/tests/test_smoke.py 中的TestPCG64DXSM。三、弃用与过期弃用API 清理路线图3.1 本版本正式移除的旧 API过期弃用移除项原弃用版本替代方案np.unravel_index的dims关键字参数1.16改用shape参数C APIPyUFunc_GenericFunction1.19直接通过 Python API 调用 ufuncC APIPyUFunc_SetUsesArraysAsData1.19——numpy.polynomial中的PolyBase类1.9.0使用抽象基类ABCPolyBase未使用的PolyError、PolyDomainError异常——从numpy.polynomial中移除对应变更见 numpy/polynomial/_polybase.pyABCPolyBase为现存的抽象基类。若旧代码中仍在使用这些符号升级到 1.21 后需要立即修复。3.2 新引入的弃用警告1.dtype属性必须返回真正的dtype当传入np.dtype或dtypeobj参数的对象其.dtype属性不是 dtype 时现在会发出DeprecationWarning。NumPy 将停止对.dtype结果做递归强制转换——自定义类的.dtype应直接返回一个真实的numpy.dtype实例。2np.convolve/np.correlate的mode参数不再接受简写此前mode参数可传不区分大小写或不精确匹配的取值如s、v、f现在会发出警告。请始终传完整的same、valid、full。3np.typeDict正式弃用np.typeDict是np.sctypeDict的别名已存在超过 14 年现在每次访问都会发出弃用警告请改用np.sctypeDict。4数组创建期间的特殊属性访问异常不再被静默吞掉当对象在访问__array__或__array_interface__时抛出异常AttributeError除外现在会给出警告。要消除警告自定义类型应保证这些属性访问抛出的异常是AttributeError。5四个ndarray.ctypes方法弃用以下四个未文档化的实现细节方法被弃用请改用对应属性弃用方法改用属性_ctypes.get_data_ctypes.data_ctypes.get_shape_ctypes.shape_ctypes.get_strides_ctypes.strides_ctypes.get_as_parameter_ctypes._as_parameter_四、兼容性说明升级到 1.21 前必须了解的行为变化4.1 ufunc 错误类型与__array_ufunc__相关变化错误类型更精确ufunc 在非法输入上可能抛出不同的异常主要变化是把部分RuntimeError替换为语义更贴切的TypeError同一调用存在多个错误时抛出的具体错误可能与旧版本不同。__array_ufunc__参数预校验NumPy 现在会在分发调用__array_ufunc__前对参数做部分校验此前非法参数如不存在的关键字参数在已知会发生分发时会被直接透传。位置参数分发的语义收窄对于reduce、accumulate、reduceat此前所有位置参数都可能被询问是否处理 ufunc 调用取决于参数按位置还是按关键字传入。现在 NumPy 只对输入与输出数组做分发例如np.add.reduce永远不会就where数组做分发。4.2Generator.uniform参数校验np.random.Generator.uniform现在强制要求high - low 0当low high时抛出ValueError。此前乱序输入会被接受并静默交换生成的值等价于high (low - high) * random()——升级后这类代码将直接报错。4.3 构建系统/usr/include从默认包含路径移除使用numpy.distutils构建包时默认包含路径不再包含/usr/include该路径通常由编译器自动添加硬编码会引发问题。若遇到问题可参考 PR 18658 中记录的 workaround 或提交 issue。4.4 比较 ufunc 的dtype参数语义变化当比较类 ufuncequal、less等使用dtype或signature参数时未来它将被视为期望的输出dtypenp.equal(2, 3, dtypeobject) # 未来将返回 object 数组现在给出 FutureWarning np.equal(None, None, dtypeobject) # 当前即返回 object 数组由于比较运算通常只返回布尔数组提供任何其他 dtype 在未来都会报错当前给出DeprecationWarning。4.5 ufunc 的dtype与signature参数忽略元数据并收紧校验dtype与signature参数同样适用于np.add.reduce、np.sum等归约在提供的 dtype 非 basic dtype 时会发出警告。NumPy 几乎总是忽略这些输入上的元数据、字节序或时间单位现在将总是忽略且一旦字节序或时间单位发生变化就直接报错# 此前忽略字节序非本机字节序时受影响——现在报错 np.add(3, 5, dtypei32) # 影响最大的是 timedelta/datetime arr np.arange(10, dtypem8[s]) np.add(arr, arr, dtypem8[ns]) # 此前总是忽略 ns 时间单位 np.maximum.reduce(arr, dtypem8[ns]) # 此前确实使用 ns与 arr.dtype 不同——现在返回通用时间单位或 arr 的单位 np.add(3, 5, dtypem8[ns]) np.maximum(arr, arr, dtypem8[ns]) # 现在返回 s取自 arr迁移建议大多数情况下传dtypenp.timedelta64即可表示不带单位与字节序的通用timedelta64若需精确指定输出 dtype可通过转换输入或提供out输出数组实现。4.6 ufuncsignature.../dtype的泛化与 casting 收紧由于类型提升逻辑变化np.ufunc(1.0, 1.0, signature...)或dtype...在 1.21 中可能选出与 1.20 不同的内核循环。此前signature会放松输入 casting 检查与castingunsafe组合时可能导致输入被不安全降精度。现在casting 保证安全signature只提供部分时如signature(float64, None, None)可能找不到循环而报错此时需提供完整 signature 以强制转换输入dtypefloat64语义微调现在严格只约束输出 dtype等价于signature(None, None, float64)两个输入一个输出的 ufunc。若首次查找失败NumPy 通常还会回退搜索signature(float64, float64, float64)循环。预计受此影响的用户极少但依赖dtype强制输入转换的代码需要检查。4.7 编译clang 强制严格浮点模型NumPy distutils 在 clang 编译时总会追加-ffp-exception-behaviorstrict标志。clang 默认的非严格模式允许编译器生成不正确设置浮点告警/错误的代码此改动确保浮点异常语义符合预期。五、C API 变化5.1ufunc-type_resolver与 type tuple 规范化NumPy 现在会在调用类型解析函数前对 type tuple 参数做规范化。需要注意的是调用类型解析器属于遗留行为NumPy 在可行时不会这样做。强烈不建议直接调用ufunc-type_resolver或PyUFunc_DefaultTypeResolver若调用将强制使用规范化后的 type tuple。提供自定义类型解析器作为 ufunc 回调注册预计在多数场景下仍可正常工作。六、新特性详解6.1 面向平台相关标量精度的 mypy 插件本版本新增 mypy 插件用于自动分配numpy.number子类中平台相关类型的精度包括np.int_、np.intp、np.longlong等。该插件完全可选但不用插件时这些类在 mypy 视角下精度会被推断为typing.Any。在 mypy 配置文件中启用[mypy] plugins numpy.typing.mypy_plugin第二个相关扩展gh-18322插件现在还会移除当前平台不可用的扩展精度类型注解例如平台不支持时移除np.float128。不使用插件时mypy 会认为所有扩展精度类型在所有平台都可用。6.2 浮点打印新参数min_digitsdragon4 浮点打印函数np.format_float_positional与np.format_float_scientific新增min_digits参数实现在 numpy/_core/arrayprint.py底层由 numpy/_core/src/multiarray/dragon4.c 的 dragon4 算法驱动add_digits digit_mode DigitMode_Unique ? min_digits : precision。在uniqueTrue模式下保证至少打印给定数量的有效数字即使多余数字对唯一定位该值并非必需与precision设置打印数字上限互为对应uniqueFalse固定精度模式下无效果数字个数由precision决定校验规则min_digits不能大于precision否则抛出ValueError。import numpy as np # uniqueTrue 下保证至少输出 8 位有效数字 print(np.format_float_positional(np.float32(np.pi), min_digits8)) print(np.format_float_scientific(np.float32(np.pi), min_digits8))6.3 f2py 支持 Fortran 抽象接口块np.f2py现在可以解析 Fortran 的 abstract interface blocks便于从更现代的 Fortran 源码生成 Python 扩展相关实现位于 numpy/f2py 模块。6.4 通过环境变量配置 BLAS/LAPACK自动探测已安装的 BLAS/LAPACK 库可以通过环境变量绕过NPY_BLAS_LIBS/NPY_LAPACK_LIBS直接使用其中的链接标志语言假定为 F77。这对自动化构建已知确切 BLAS/LAPACK 实现特别有用典型场景是通过桩库链接在运行时替换实际实现NPY_CBLAS_LIBS可选配合NPY_BLAS_LIBS设置后将定义HAVE_CBLAS并把变量内容追加到链接标志。6.5 可运行时下标化的numpy.typing.NDArray新增numpy.typing.NDArray是np.ndarray[Any, np.dtype[~Scalar]]的运行时可下标别名定义于 numpy/typing/init.py。它用于为指定 dtype、形状未指定的数组提供注解。注意截至 1.21NumPy 尚不支持数组形状的注解预计未来随 PEP 646 改变。import numpy as np import numpy.typing as npt from typing import Any print(npt.NDArray) # numpy.ndarray[typing.Any, numpy.dtype[~ScalarType]] print(npt.NDArray[np.float64]) # numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]] NDArrayInt npt.NDArray[np.int_] a: NDArrayInt np.arange(10) def func(a: npt.ArrayLike) - npt.NDArray[Any]: return np.array(a)七、功能改进7.1np.unwrap支持任意period相位解缠绕的区间宽度不再局限于2 * pi解缠绕度degree或其他自定义区间变得更方便实现见 numpy/lib/_function_base_impl.py默认period2*pi输出 dtype 为np.result_type(p, period)整数周期可保持整数 dtypeimport numpy as np from numpy import unwrap phase_deg np.mod(np.linspace(0, 720, 19), 360) - 180 print(phase_deg) # array([-180., -140., -100., -60., -20., 20., 60., 100., 140., # -180., -140., -100., -60., -20., 20., 60., 100., 140., # -180.]) print(unwrap(phase_deg, period360)) # array([-180., -140., -100., -60., -20., 20., 60., 100., 140., # 180., 220., 260., 300., 340., 380., 420., 460., 500., # 540.])7.2np.unique现在只返回单个NaN此前对含多个NaN的数组做np.unique返回结果中每个原始NaN都对应一个NaN。现在改进为返回数组末尾只有一个NaN。对于复数数组所有NaN无论位于实部还是虚部视为等价返回代表取字典序最小的那个字典序定义同np.sort对复数数组的处理。7.3Generator.rayleigh与Generator.geometric性能提升两者的随机变量生成均基于指数随机变量的变换原先基于 log 的逆 CDF 变换被替换为基于Ziggurat 算法的指数变量生成器性能显著提升。注意此改动会改变这两个分布产出的随机数流——依赖固定流进行结果复现的代码需要更新预期值。7.4 占位注解改进所有此前标注为typing.Any的占位注解被改进在合适处替换为显式的函数定义、类或其他对象进一步收紧类型检查精度。八、性能改进8.1 整数除法引入 libdivideNumPy 数组的整数除法在除数为常量时使用 libdivide。常量除数场景循环、数值算法中常见的除以固定步长收益最大。8.2np.save/np.load小数组加速np.save对小数组显著提速np.load仅在序列化版本 (3, 0)时对小数组提速。两者都通过移除仅与 Python 2 相关的检查实现同时保持对 Python 2 创建数组的兼容性。九、行为变更9.1np.piecewise输出类型匹配输入类型当ndarray子类作为np.piecewise输入时它们会传给内部函数输出现在同样保持该子类类型不再退化为基类ndarray。9.2 macOS 启用 Accelerate Framework随着 macOS 11.3 的发布此前 NumPy 使用 Accelerate Framework 的 BLAS/LAPACK 实现时遇到的多项问题已解决本版本在 macOS 上启用 Accelerate Framework 作为可选后端。若发现额外问题官方建议通过 Apple 的反馈助手工具提交 bug 报告NumPy 团队将及时处理并持续维护相关 BLAS/LAPACK 库。十、升级清单与迁移要点综合以上内容从 1.20 升级到 1.21.0 时建议按如下清单自查随机数若并行场景依赖PCG64的统计质量评估切换到PCG64DXSM若依赖rayleigh/geometric的固定随机流注意流已改变ufunc检查dtype/signature用法特别是 timedelta 单位、字节序、比较运算改为传通用 dtype 或使用out检查dtype是否被用于强制输入转换已移除 API替换PolyBase→ABCPolyBaseunravel_index(dims...)→shape移除typeDict、ctypes四个get_*方法及mode简写异常语义Generator.uniform的low high将抛ValueErrorufunc 错误类型可能变化构建系统注意/usr/include不再默认加入包含路径clang 编译新增严格浮点标志类型检查启用numpy.typing.mypy_plugin以获得平台相关标量精度的精确推断并用numpy.typing.NDArray标注数组数值输出np.unique的 NaN 去重行为、piecewise的返回子类行为已变化。这些变更共同指向 NumPy 2.x 的方向性调整——更严格的 dtype 语义、更强健的类型系统与新随机数基础设施。建议在升级后跑通仓库测试套件如numpy/tests下的 test_public_api.py 等以尽早暴露兼容性问题。【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表