NumPy 1.21.0 版本发布说明:核心特性、PRNG 演进与工程化升级全解析
【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy
本篇文章基于 NumPy 官方仓库的 1.21.0 版本变更日志 编写,系统梳理该版本引入的新功能、性能优化、弃用项与工程化改进,并对照仓库源码与测试用例提供可验证的实现依据。读完本文,你将了解 NumPy 1.21.0 的核心变更全景,掌握PCG64DXSM、numpy.typing.NDArray等新特性的正确用法,并理解其发布与版本管理流程。
版本概况:175 位贡献者与 581 个合并 PR
根据官方变更日志,NumPy 1.21.0 共获得175 位贡献者的参与(其中带+标记的为首次提交补丁的新贡献者),累计合并了581 个 pull request。这是 1.x 系列中规模较大的一个版本,变更横跨:
- 新功能(
ENH):新增位生成器、类型注解、新参数支持等; - 性能优化(
SIMD):围绕 CPU 指令集分派的大量内联汇编级优化; - 弃用(
DEP):为 2.0 时代的 API 清理做铺垫; - 构建与发布(
BLD/REL):版本管理工具链的迁移(versioneer、towncrier); - 文档与类型标注(
DOC/TYP):超过百项的文档修正与pyi存根完善。
由于 1.21.0 是"为 2.0 做准备"的版本,其变更日志中大量DEP与API条目都指向后续 2.0 的破坏性变更,理解这一版本有助于把握 NumPy 演进的节奏。
新随机数生成器 PCG64DXSM:更安全的 PCG 变体
1.21.0 最受关注的新功能之一是新增的位生成器PCG64DXSM(PR #18906、#18940)。它与既有PCG64同属 O'Neill 的 PCG 家族,但采用了更强的 DXSM 输出函数。
从源码实现看,该生成器定义于 numpy/random/_pcg64.pyx,其文档字符串明确说明:
PCG-64 DXSM 是 O'Neill 置换同余生成器的 128 位实现,周期为 $2^{128}$,支持任意步数推进(
advance)以及 $2^{127}$ 个流。与PCG64的区别在于:使用更强的 DXSM 输出函数、在 LCG 中使用 64 位 "cheap multiplier",并且先输出状态再推进(而非 advance-then-output)。
基本用法
from numpy.random import Generator, PCG64DXSM, SeedSequence rng = Generator(PCG64DXSM(12345)) x = rng.standard_normal(10)并行场景:配合 SeedSequence.spawn
源码文档明确推荐并行场景下使用SeedSequence.spawn派生互不相关的子流:
from numpy.random import Generator, PCG64DXSM, SeedSequence sg = SeedSequence(1234) rg = [Generator(PCG64DXSM(s)) for s in sg.spawn(10)]状态与播种细节
从 numpy/random/_pcg64.pyx 可以确认:
- 状态向量由 2 个 128 位无符号整数构成(外部以 Python int 表示):一个是 LCG 推进的 PRNG 状态,另一个是 LCG 使用的固定奇数增量;
- 输入种子统一交给
SeedSequence处理生成这两个值,增量不可独立设置; __init__通过_seed_seq.generate_state(4, np.uint64)获取 4 个 64 位字来初始化状态与增量;- 底层通过
pcg64_cm_uint64/pcg64_cm_uint32/pcg64_cm_double等函数指针向Generator提供原生随机数。
兼容性保证
PCG64DXSM明确承诺:固定种子必然产生完全相同的随机整数流(见 numpy/random/_pcg64.pyx)。测试用例 numpy/random/tests/test_smoke.py 中TestPCG64DXSM与TestPCG64采用相同的推进步长($2^{63}+2^{31}+2^{15}+1)与种子[12345]参与全套冒烟测试,印证其与既有生成器同等严格的质量验证体系。
PCG64 与 PCG64DXSM 对比
| 维度 | PCG64 | PCG64DXSM |
|---|---|---|
| 输出函数 | 较弱(易受统计攻击影响) | 更强的 DXSM 输出函数 |
| LCG 乘法器 | 普通乘法 | 64 位 "cheap multiplier" |
| 输出时机 | advance-then-output | 先输出后推进 |
| 兼容性 | 1.17+ 默认生成器 | 1.21.0 新增,独立流 |
注意:1.21.0 中默认随机数生成器仍是
PCG64,PCG64DXSM作为更安全的替代选项提供。
类型注解:numpy.typing.NDArray 与平台相关精度推断
1.21.0 在静态类型(numpy.typing)方向投入大量工作,核心成果包括:
- 新增
npt.NDArray别名(PR #18935):一个可运行时下标操作的np.ndarray别名,用于函数签名标注; - mypy 插件(PR #17843、#18322):推断平台相关的
np.number精度与扩展精度类型; - 大量模块补齐注解:
np.lib.ufunclike、np.lib.index_tricks、np.lib.arrayterator、np.core.einsumfunc、np.lib.utils、np.core.numerictypes、np.lib.NumpyVersion等(PR #18377、#18397、#18545、#18390、#18944、#18818、#18990)。
NDArray的定义与导出可参见 numpy/typing/init.py:
from numpy._typing import ArrayLike, DTypeLike, NBitBase, NDArray __all__ = ["ArrayLike", "DTypeLike", "NBitBase", "NDArray"]典型用法:
import numpy.typing as npt def normalize(x: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: return x / x.max()这批注解工作为 2.x 时代numpy.typing成为正式 API 奠定了坚实基础。
弃用与兼容性:为 2.0 铺路
1.21.0 的弃用公告贯穿多个方向,读懂这些DEP条目是升级到 2.x 的关键:
- 字符串与数字/布尔值的隐式提升弃用(PR #18116、#18999、#19175):
np.array(["a", 1])这类混合提升开始发出FutureWarning,最终推迟到后续版本正式失效; np.typeDict正式弃用(PR #17586);np.testing.dec模块弃用(PR #18051);data_type.dtype属性弃用(PR #13578);correlate的mode参数解析移入 C 层,不再接受非精确的旧解析(PR #17492);unravel_index的dims参数名最终确立为shape(PR #17900);- 对 array-like 要求
__len__的未来警告(PR #17973); - 禁用
PyUFunc_GenericFunction与PyUFunc_SetUsesArraysAsData(PR #18697),收紧 C API 面。
字符串提升弃用路径的引用计数修复(PR #18931)、以及"推迟字符串与数字提升的弃用/未来警告"(PR #19175)表明:这类影响面广的变更采用分阶段策略,确保用户有足够迁移窗口。
SIMD 与性能优化:指令级加速
1.21.0 是 SIMD 分派框架(NPYV,universal intrinsics)全面铺开的版本,围绕 numpy/_core/src 下的 SIMD 代码 展开大量内联优化:
- 整数除法改用 libdivide:
floor divide(PR #17727)与有符号整数除法(PR #18766)引入 libdivide 算法,将除法转为乘法+位移;对应新增快速整数除法内建函数(PR #18178); packbits的 AVX2/AVX512F/VSX 优化(PR #17102);sin/cos等超越函数迁移到 NPYV 通用内建(PR #17587);einsum子模块的乘加、dot、sum 优化(PR #17782、#17994、#18012、#18194);count_nonzero的 SIMD 加速(PR #17958、#18183);exp/log/frexp/ldexp迁移至 SIMD 分派(PR #18101),并修复 AVX/AVX512 下的下溢报告问题(PR #18920、#18933);min/max值比较的 SIMD 实现(PR #18863、#18882、#18889);- 旧 CPU 分派器(算术部分)被 NPYV 取代(PR #17985)。
配套地,构建系统新增了对 x86 基线(ubuntu-20.04 native baseline,PR #17960)、ppc64le、FreeBSD ARM、Fujitsu 编译器(PR #17792)、Apple M1(PR #18538)等平台与编译器的支持与修复。
工程化升级:versioneer 与 towncrier 发布流程
1.21.0 完成了两项重要的工程化迁移:
- 版本管理迁移到 versioneer(PR #17956、#17974、#18205):由 git 标签自动推导版本号,并支持时间戳标记开发版本(PR #17886),从工具链层面避免版本漂移;
- 发布说明改用 towncrier 聚合(PR #18790、#18982、#18930):开发者只需在 doc/release/upcoming_changes 目录下按
<PR号>.<类型>.rst命名提交"新闻片段"。
新闻片段的规范见 doc/release/upcoming_changes/README.rst:类型包括new_function、deprecation、future、expired、compatibility、c_api、new_feature、improvement、performance、typing、change、highlight。发布时执行:
towncrier build --version "<version>"(该命令详见 doc/HOWTO_RELEASE.rst 的发布流程说明。)本地预览可使用:
towncrier build --draft --version 1.18这一机制保证了 changelog 与每个 PR 一一对应、可追溯——本文所依据的 1.21.0-changelog.rst 正是该流程的产物。
其他值得关注的变更
numpy.save对小数组的性能改进(PR #18657);mean/var的where关键字修复(PR #18560);unique对 NaN 条目的正确处理(PR #18070);np.in1d对 object 数组的 bug 修复(PR #18369);tril_indices/triu_indices性能提升(PR #18176);piecewise子类安全化(PR #18110);np.clip文档补充a_min > a_max特殊用例说明(PR #18786)。
结语
NumPy 1.21.0 是一个承上启下的版本:新增PCG64DXSM强化随机数基础设施,类型注解体系走向成熟,SIMD 优化大规模落地,同时通过一波有条不紊的弃用为 2.0 清理 API 面。对开发者而言,建议重点关注字符串提升弃用带来的迁移工作,并将新代码中的随机数场景优先考虑PCG64DXSM。深入阅读本仓库中的 numpy/random/_pcg64.pyx、numpy/typing 与 numpy/random/tests/test_smoke.py,可以进一步验证本文涉及的全部实现细节。
【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考