NumPy 1.10.2 发布说明深度解析:relaxed stride 回滚、Fortran 视图弃用与关键缺陷修复
2026/9/20 22:40:39 网站建设 项目流程

NumPy 1.10.2 发布说明深度解析:relaxed stride 回滚、Fortran 视图弃用与关键缺陷修复

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

本篇技术指南以 NumPy 1.10.2 官方 Release Notes 为主体,系统梳理该维护版本在兼容性策略上的重大调整——relaxed stride checking 回滚为非默认、Fortran 连续数组视图相关行为变更与弃用,以及 34 个已修复 issue 与 36 个合并 PR 的分类解读。文章同时结合当前仓库源码(numpy.i、ndarraytypes.h、ma/core.py 等)逐项验证修复原理。读完本文,你将掌握:1.10.x 时代 Fortran/C 连续性与视图语义的变迁脉络;numpy.iSWIG 绑定中 Fortran 连续性宏的正确用法;以及marandomlib等模块中若干历史缺陷的根因与修复方式。

版本概览与支持范围

NumPy 1.10.2 是针对 1.10.1 中暴露的一系列缺陷的维护性发布(bugfix release)。发布说明原文指出:"This release deals with a number of bugs that turned up in 1.10.1 and adds various build and release improvements."——即该版本一方面集中修复 1.10.1 引入的回归问题,另一方面补充了大量构建(build)与发布(release)流程层面的改进。

需要特别留意的是,文档中有一处明显的笔误:1.10.2 的说明文字写为 "Numpy 1.10.1 supports Python 2.6 - 2.7 and 3.2 - 3.5.",此处实际指代的是1.10.2 及其所在 1.10 系列支持的 Python 版本范围——Python 2.6/2.7 与 Python 3.2/3.5。读者在引用时应以 1.10 系列整体为准,不要误解为仅 1.10.1 支持这些版本。

兼容性说明(Compatibility Notes):stride 语义的收敛与回退

1.10.2 的兼容性变化是本版本最具技术深度的部分,全部围绕数组连续性(contiguity)与视图(view)语义展开,核心关键词是 relaxed stride checking。

Relaxed stride checking 不再是默认行为

变更内容:在 1.10 系列中,relaxed stride checking 从默认开启被回退为默认关闭。

技术背景:relaxed stride checking 是 NumPy 对数组连续性判定规则的放宽——在严格模式下,只有当数组的 stride 完全符合"行优先(C 顺序)"或"列优先(Fortran 顺序)"理论值时,才被标记为对应连续;而 relaxed 模式允许某些"实际上可被当作连续处理"的非标准 stride 布局也被认可。

回退原因:发布说明明确指出,回退源于向后兼容性问题——"There were back compatibility problems involving views changing the dtype of multidimensional Fortran arrays that need to be dealt with over a longer timeframe."即:通过 view 修改多维 Fortran 数组的 dtype 时,relaxed stride 检查会破坏既有代码的预期行为,该问题需要更长时间来妥善处理,因此在 1.10 中先回退为非默认。

对应合并的 PR 为 gh-6735(MAINT: Make no relaxed stride checking the default for 1.10),并在 Merged PRs 一节中注明:"Relaxed stride checking was reverted. There were back compatibility problems involving views changing the dtype of multidimensional Fortran arrays..."

为什么 Fortran 视图与 relaxed stride 冲突:从宏定义看根因

要理解这次回退的技术根因,可以对照当前仓库中连续性判定宏的定义。在 ndarraytypes.h 中:

#define PyArray_ISONESEGMENT(m) (PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS) || \ PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS)) #define PyArray_ISFORTRAN(m) (PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) && \ (!PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)))

关键语义在于:PyArray_ISFORTRAN(m)判定为真的条件是Fortran 连续且同时非 C 连续。这意味着在传统语义中,一个数组要么是 C 连续、要么是 Fortran 连续,二者在ndim > 1的非标量数组上被视为互斥关系。

而一旦启用 relaxed stride checking,同时满足 C 连续与 Fortran 连续的数组会被一律当作 C 连续处理,这打破了"二者互斥"这一被大量既有代码依赖的隐含假设,导致通过 view 修改多维 Fortran 数组 dtype 的代码出现行为偏差。这正是发布说明所描述的回退理由在宏层面的体现。

弃用:通过 dtype 赋值改变 Fortran 数组的 shape

变更内容:本版本引入一条新的弃用(deprecation)规则——禁止对非 C 连续(non-C-contiguous)数组的dtype属性赋新描述符(descriptor),如果该赋值会导致 shape 发生变化。用文档原话:"This effectively bars viewing a multidimensional Fortran array using a dtype that changes the element size along the first axis."即:实际封堵了"沿第一个轴改变元素大小"的方式查看多维 Fortran 数组这一操作路径。

弃用动机:该弃用是为"未来始终启用 relaxed stride checking"铺路("This deprecation prepares the way to always enable relaxed stride checking")。因为在 relaxed 模式下,同时 C/Fortran 连续的数组被统一视为 C 连续,部分依赖二者互斥的代码会失效;而通过 dtype 修改 shape 恰恰是这类代码的高发场景。对应的实现 PR 为 gh-6747(DEP: Deprecate changing shape of non-C-contiguous array via descr),而 gh-6678(Getting unexpected error from: X.dtype = complex)则记录了用户在此场景下遇到的实际报错。

numpy.i 中的 SWIG 绑定修复

relaxed stride checking 的引入还暴露了一个 SWIG 绑定层面的真实 bug:array_is_fortran(a)宏此前错误地使用PyArray_ISFORTRAN来判定 Fortran 连续性,而正确做法是使用PyArray_IS_F_CONTIGUOUS

在当前仓库 tools/swig/numpy.i 中,可以同时看到新旧两种实现的分支:

%#if NPY_API_VERSION < NPY_1_7_API_VERSION /* ... 旧版 API 分支 ... */ %#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) %#else /* ... NPY_1_7 及以后的新版 API 分支(修复后的实现)... */ %#define array_is_fortran(a) (PyArray_IS_F_CONTIGUOUS((PyArrayObject*)a)) %#endif

结合上文宏定义可知:PyArray_ISFORTRAN要求"F 连续且非 C 连续",因此在 relaxed stride 语义下,一个同时 C/Fortran 连续的数组会被误判为"不是 Fortran 连续",进而导致make_fortran()等函数做出错误的复制决策。

make_fortran函数的修复后逻辑位于 tools/swig/numpy.i:若array_is_fortran(ary)为真则直接复用原数组指针(is_new_object = 0),否则通过PyArray_FromArrayNPY_ARRAY_F_CONTIGUOUS(旧版 API 为NPY_FORTRANORDER)标志创建一个新的 Fortran 连续副本。这一判断的正确性直接取决于array_is_fortran宏的语义。

对下游用户的实操建议:发布说明明确建议"You may want to regenerate swigged files using the updated numpy.i"——即凡是使用 SWIG 封装 NumPy 数组的项目,应使用更新后的 numpy.i 重新生成绑定代码,否则在 1.10.2 的默认(非 relaxed)模式下,Fortran 连续性判定可能仍然产生偏差。

Issues Fixed:按模块分类解读

1.10.2 共修复 34 个 issue,涉及核心数组语义、掩码数组、随机数、f2py、构建系统等多个领域。以下按模块分组解读代表性修复:

数组核心语义与视图(dtype / view / stride)

  • gh-6678X.dtype = complex(或Y = X.view(complex))报错——与上文 Fortran 视图弃用直接相关,是触发弃用规则的用户可见场景。
  • gh-6590 / gh-6771:Fortran 数组在 1.10 中的问题;np.rec.fromarrays在 1.9.2 与 1.10.1 之间丢失 dtype 元数据(metadata),由 gh-6780(BUG: metadata is not copied to base_dtype)修复。
  • gh-6491 / gh-6572stride_tricks广播数组时报错,对应修复 PR gh-6556(BUG: Error in broadcast_arrays with as_strided array)。
  • gh-6575split产生维度数量错误的空数组;gh-6576 将修复回退,因为其"修正"了 1.11 才应有的行为(而 1.9 已存在该行为)。

数学函数(median / partition / interp / inner)

  • gh-6462:空数组求中位数抛出IndexError。当前实现位于 numpy/lib/_function_base_impl.py(def median),对应修复 PR gh-6527(BUG: Fix the IndexError when taking the median of an empty array)。
  • gh-6530partition函数对空输入报错,由 gh-6553(BUG: Fix partition and argpartition error for empty input)修复。
  • gh-6468numpy.interpx[0]==xp[0]时错误地使用left值。当前interp实现位于 numpy/lib/_function_base_impl.py,其文档明确left仅用于x < xp[0]的情形;修复 PR 为 gh-6785(BUG: Quick and dirty fix for interp)。
  • gh-6532numpy.inner在非连续数组上偶发返回错误精度结果,由 gh-6546(BUG: Fix inner product regression for non-contiguous arrays)修复。

掩码数组(numpy.ma)

  • gh-6019:结构化数组含多维列时掩码数组的repr失败,对应修复 PR gh-6094(BUG: Fixed a bug with string representation of masked structured arrays)与 gh-6813(TST,BUG: Make test_mvoid_multidim_print work for 32 bit systems)。
  • gh-6611ma.dot不再总是返回掩码数组(1.10 回归),由 gh-6653(BUG: Fix ma dot to always return masked array)修复。
  • gh-6667ma.make_maskma.nomask输入处理不正确。当前实现位于 numpy/ma/core.py,其 docstring 明确约定:"If the dtype is flexible ... This is ignored whenmisnomask, in which casenomaskis always returned."修复 PR 为 gh-6668(BUG: ma.make_mask should always return nomask for nomask argument)。nomask本身定义于 numpy/ma/core.py:nomask = MaskType(0)
  • gh-6537 / gh-6538ma.atleast_*对标量参数应返回数组、ma.masked_values按请求收缩掩码,分别由 gh-6537、gh-6538 修复。

记录数组(recarray)

  • gh-6467:记录数组访问出现性能回归,由 gh-6208(MAINT: Speedup field access by removing unneeded safety checks)与 gh-6562(BUG: Disable view safety checks in recarray)缓解。
  • gh-6497:recarray 上的 reduce 操作失败;gh-6500 修复"recarray 视为子数组时不转换为 np.record 类型"的问题。
  • gh-6636numpy.recarray嵌套 dtype 内存泄漏,由 gh-6642(BUG: Fix memleak in _convert_from_dict)修复。
  • gh-6641:按字段子集化 recarray 得到结构化数组,由 gh-6643(ENH: make recarray.getitem return a recarray)改为返回 recarray。

随机数模块(numpy.random)

  • gh-6602numpy.random.__all__缺失choicedirichlet,导致from numpy.random import *无法导入这两个函数。当前仓库 numpy/random/init.py 的__all__中已同时包含'choice''dirichlet',修复 PR 为 gh-6614(BUG: Add choice and dirichlet to numpy.random.all)。

f2py 相关

  • gh-6563:f2py 的intent(out)在新版本中失效。
  • gh-6718:pip 安装的 numpy-1.10.1 在 virtualenv 中 f2py 测试失败,由 gh-6756(TST: only test f2py, not f2py2.7 etc)修复。
  • gh-6719:Cython 文件编译报 "Pythonic division not allowed without gil",由 gh-6721 修复。
  • 另见 gh-6487(f2py 数组定义中允许嵌套参数)、gh-6488(f2py 扩展 common block 而非覆盖)。

构建与发布流程

  • gh-6495:gfortran 无法识别命令行选项-ffpe-summary
  • gh-6569python setup.py build_ext -i后无法运行测试,由 gh-6577 修复。
  • gh-6675:master 与 1.10 分支的优化 BLAS 检测失效,由 gh-6717(BUG: Readd fallback CBLAS detection on linux)与 gh-6757(BUG: link cblas library if cblas is detected)修复。
  • gh-6478:OS X 构建的 Intel 编译器标志修复。
  • gh-6481:LIBPATH 含空格时 Python 2.7+ 与 Win32 平台的支持。
  • gh-6807 / gh-6781:Windows 与 Travis-CI 测试基础设施问题(gh-6783 适配新 Google 基础设施)。
  • gh-6817:禁用 32 位 msvc9 编译器的 npy_rint 优化(配合 gh-6698 的np.rint大整数测试)。

Merged PRs 综述与三次关键回退

1.10.2 共合并 36 个 PR(含对 master 的 backport,backport 时同时列出原 PR 编号)。除上述按 issue 对应的修复外,还有若干流程性改进值得留意:

  • 测试与质量:gh-5773(用 pytest 时隐藏测试辅助工具 traceback)、gh-6686(修复 assert_string_equal 的 bug)、gh-6460(以侵入性更小的方式替代 os.environ.clear)、gh-6775(补齐缺失的from __future__样板)。
  • 发布工具:gh-6474(更新 Paver 脚本与测试警告自动切换)、gh-6501 / gh-6558(新增文档 "make upload" 命令)、gh-6579(修正 doc upload 规则)。
  • 杂项:gh-6697(修复 PyArray_FROM_OT 宏定义中多余的冒号)、gh-6526(-OO 模式下 setup.py 中__doc__的使用)。

特别需要关注的是本版本的三次"回退(revert)"决策,它们体现了维护团队在兼容性与新特性之间的权衡:

  1. mingwpy 初始支持被回退(gh-6536,对应回退 gh-5614):因对非 Windows 构建造成问题而撤销。
  2. np.lib.split的修复被回退(gh-6576,对应回退 gh-6376):因该"修复"提前引入了 NumPy 1.11 才应有的行为(而该行为在 1.9 已存在),为避免 1.10.2 偏离既定语义而回退。
  3. relaxed stride checking 回退为非默认(gh-6735):即前文 Compatibility Notes 的核心变更,同时配合 gh-6726(BUG: Fix bugs exposed by relaxed stride rollback)清理回退暴露的问题。

附加说明:1.10.1 的 RuntimeWarning/DeprecationWarning 回归

发布说明末尾专门记录了一个 1.10.1 的回归:该版本中的一个 bug 导致依赖 NumPy 的项目中RuntimeWarningDeprecationWarning被当作异常抛出(即警告升级为错误)。此问题在 1.10.2 中已修复("That has been fixed.")。

这一看似细小的修复对生态影响重大——若警告被强制升级为异常,任何依赖 NumPy 的第三方库中触发已弃用 API 的代码都会直接崩溃,而不是仅打印警告。对于从 1.10.1 升级的用户,这是升级到 1.10.2 的最直接理由之一。

总结与升级建议

NumPy 1.10.2 作为一个维护版本,其价值集中在三方面:

  1. 语义收敛:将 relaxed stride checking 回退为非默认,并弃用"通过 dtype 赋值改变非 C 连续数组 shape"的操作,为后续版本彻底理清 Fortran/C 连续性与视图的关系铺路;
  2. 缺陷修复:覆盖 ma、recarray、random、lib(median/partition/interp/inner)、f2py 等多个模块的 34 个 issue,其中多数为 1.10.1 引入的回归;
  3. 构建与发布改进:修复 BLAS 检测、Intel/gfortran 编译器标志、Windows 与 CI 基础设施问题,并完善文档发布工具链。

对于仍在 1.10.x 系列的用户,建议立即升级至 1.10.2:一方面规避 1.10.1 中警告升级为异常的回归,另一方面获得上述全部缺陷修复;使用 SWIG 封装 NumPy 的项目则应基于更新后的 tools/swig/numpy.i 重新生成绑定文件,确保 Fortran 连续性判定与 1.10.2 的语义一致。

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

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询