【问题标题】:Numpy floating point rounding errorsNumpy 浮点舍入错误
【发布时间】:2015-10-06 03:49:08
【问题描述】:

在搜索一些 numpy 的东西时,我遇到了一个讨论 numpy.dot() 的舍入精度的问题:

Numpy: Difference between dot(a,b) and (a*b).sum()

由于我的桌子上碰巧有两台(不同的)带有 Haswell-CPU 的计算机,它们应该提供 FMA 和一切,我想我会测试 Ophion 在第一个答案中给出的示例,我得到的结果是有点让我吃惊:

在更新/安装/修复 lapack/blas/atlas/numpy 后,我在两台机器上都得到以下信息:

>>> a = np.ones(1000, dtype=np.float128)+1e-14
>>> (a*a).sum()
1000.0000000000199999
>>> np.dot(a,a)
1000.0000000000199948

>>> a = np.ones(1000, dtype=np.float64)+1e-14
>>> (a*a).sum()
1000.0000000000198
>>> np.dot(a,a)
1000.0000000000176

所以标准乘法 + sum() 比 np.dot() 更精确。然而 timeit 证实 .dot() 版本对于 float64 和 float128 来说都更快(但不多)。

谁能解释一下?

编辑:我不小心删除了有关 numpy 版本的信息:1.9.0 和 1.9.3 与 python 3.4.0 和 3.4.1 的结果相同。

【问题讨论】:

  • 有趣的是,我只在 NumPy 1.9.2 上得到这种差异,而不是在 NumPy 1.8.2 上。两者都使用 blas + lapack(不是 atlas)。在 NumPy 1.8.2 中,结果与 dot 和 sum 相同,表明舍入事件相同,在 NumPy 1.9.2 上,乘法 + sum() 更精确。
  • 还有github.com/numpy/numpy/pull/3685,这是对sum 进行更改的地方。
  • 谁能确认 ATLAS 使用 FMA?我知道最新的 MKL 确实如此,应该是一个有趣的比较。

标签: python numpy precision


【解决方案1】:

看起来他们最近在ndarray.sum 中添加了一个特殊的Pairwise Summation,以提高数值稳定性。

来自PR 3685,这会影响:

all add.reduce calls that go over float_add with IS_BINARY_REDUCE true
so this also improves mean/std/var and anything else that uses sum.

有关代码更改,请参阅 here

【讨论】:

  • 一种“分而治之”的算法。是的,这是有道理的,谢谢。
  • 这是否意味着我们实际上更适合使用替代策略来计算矩阵而不是集成函数?这很讽刺,因为 numpy 的目的是为了简化科学工作。
猜你喜欢
  • 1970-01-01
  • 2014-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多