python/numpy中的浮点数学在计算机上不可复制

python/numpy中的浮点数学在计算机上不可复制,python,numpy,floating-point,blas,Python,Numpy,Floating Point,Blas,通过比较两台不同机器上的浮点计算结果,它们一致地产生不同的结果。下面是一个复制该行为的简化示例: 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

通过比较两台不同机器上的浮点计算结果,它们一致地产生不同的结果。下面是一个复制该行为的简化示例:

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]

但我也可以得到相同的结果,例如在同一年份的两台MacBook上运行。这种情况发生在具有相同版本的Python和numpy的机器上,但不一定链接到相同的BLAS库(例如Mac上的accelerate framework,Ubuntu上的OpenBLAS)。然而,不同的数值库不应该都符合相同的IEEE浮点标准并给出完全相同的结果吗

浮点计算并不总是可重复的

如果使用相同的可执行映像、输入、使用相同的编译器和相同的编译器设置(开关)构建的库,您可能会在不同的计算机上获得可复制的浮点计算结果

但是,如果使用动态链接的库,由于多种原因,可能会得到不同的结果。首先,作为Veedrac,它可能会在不同的体系结构上为其例程使用不同的算法。其次,编译器可能会根据开关(各种优化、控制设置)生成不同的代码。甚至
a+b+c
也会在机器和编译器之间产生不确定的结果,因为我们无法确定计算顺序和中间计算的精度

阅读为什么不能保证在不同的
IEEE 754-1985
实现上获得相同的结果。新标准(
ieee754-2008
)试图更进一步,但它仍然不能保证不同实现之间的结果相同,因为例如,它允许实现者选择何时检测到tinynes(下溢异常)


有关浮点决定论的更多信息,请参见。

种子在所有机器上都相同吗?是的,np.random.seed(0)产生相同的状态,因为所有机器都使用相同版本的numpy.out interest,numpy的哪个版本?使用不同的种子编号是否也有相同的行为?BLAS库可能使用不同的算法,因此期望它们总是给出相同的输出似乎很奇怪。至少在Python级别上,我们可以确定求值顺序和中间精度,比如
a+b+c
:求值顺序是确定的,中间结果被强制存储(因此不可预测的寄存器溢出导致的不确定性不是问题)。在一次算术运算中仍然存在双舍入的可能性,尽管这个问题正在慢慢变得越来越少。。。