python/numpy 中的浮点数学不能跨机器重现
Floating point math in python / numpy not reproducible across machines
比较几台不同机器的浮点计算结果,它们始终产生不同的结果。这是一个重现该行为的精简示例:
import numpy as np
from numpy.random import randn as rand
M = 1024
N = 2048
np.random.seed(0)
a = rand(M,N).astype(dtype=np.float32)
w = rand(N,M).astype(dtype=np.float32)
b = np.dot(a, w)
for i in range(10):
b = b + np.dot(b, a)[:, :1024]
np.divide(b, 100., out=b)
print b[0,:3]
不同的机器产生不同的结果,例如
- [-2.85753540e-05 -5.94204867e-05 -2.62337649e-04]
- [-2.85751412e-05 -5.94208468e-05 -2.62336689e-04]
- [-2.85754559e-05 -5.94202756e-05 -2.62337562e-04]
但我也可以获得相同的结果,例如运行 在同一年份的两本 Mac 书籍上。这发生在具有相同版本 Python 和 numpy 的机器上,但不一定链接到相同的 BLAS 库(例如 Mac 上的加速框架,Ubuntu 上的 OpenBLAS)。然而,不同的数值库不应该都符合相同的 IEEE 浮点标准并给出完全相同的结果吗?
浮点计算并不总是可重现的。
如果您使用相同的可执行映像、输入、使用相同的编译器和相同的编译器设置(开关)构建的库,您可能在不同机器上获得可重现的浮动计算结果。
但是,由于多种原因,如果您使用动态链接库,您可能会得到不同的结果。首先,作为 Veedrac ,它可能会在不同的体系结构上对其例程使用不同的算法。其次,编译器可能会根据开关(各种优化、控制设置)生成不同的代码。即使 a+b+c
也会在机器和编译器之间产生不确定的结果,因为我们无法确定求值顺序、中间计算的精度。
阅读 here 为什么不能保证在不同的 IEEE 754-1985
实现上获得相同的结果。新标准(IEEE 754-2008
)试图走得更远,但它仍然不能保证不同实现之间的结果相同,因为例如它允许实现者选择何时检测到微小(下溢异常)
有关浮点确定性的更多信息,请参阅 this article。
比较几台不同机器的浮点计算结果,它们始终产生不同的结果。这是一个重现该行为的精简示例:
import numpy as np
from numpy.random import randn as rand
M = 1024
N = 2048
np.random.seed(0)
a = rand(M,N).astype(dtype=np.float32)
w = rand(N,M).astype(dtype=np.float32)
b = np.dot(a, w)
for i in range(10):
b = b + np.dot(b, a)[:, :1024]
np.divide(b, 100., out=b)
print b[0,:3]
不同的机器产生不同的结果,例如
- [-2.85753540e-05 -5.94204867e-05 -2.62337649e-04]
- [-2.85751412e-05 -5.94208468e-05 -2.62336689e-04]
- [-2.85754559e-05 -5.94202756e-05 -2.62337562e-04]
但我也可以获得相同的结果,例如运行 在同一年份的两本 Mac 书籍上。这发生在具有相同版本 Python 和 numpy 的机器上,但不一定链接到相同的 BLAS 库(例如 Mac 上的加速框架,Ubuntu 上的 OpenBLAS)。然而,不同的数值库不应该都符合相同的 IEEE 浮点标准并给出完全相同的结果吗?
浮点计算并不总是可重现的。
如果您使用相同的可执行映像、输入、使用相同的编译器和相同的编译器设置(开关)构建的库,您可能在不同机器上获得可重现的浮动计算结果。
但是,由于多种原因,如果您使用动态链接库,您可能会得到不同的结果。首先,作为 Veedrac a+b+c
也会在机器和编译器之间产生不确定的结果,因为我们无法确定求值顺序、中间计算的精度。
阅读 here 为什么不能保证在不同的 IEEE 754-1985
实现上获得相同的结果。新标准(IEEE 754-2008
)试图走得更远,但它仍然不能保证不同实现之间的结果相同,因为例如它允许实现者选择何时检测到微小(下溢异常)
有关浮点确定性的更多信息,请参阅 this article。