我目前有两台机器,它们在两个向量上为np.dot
的一个实例产生不同的输出。在不深入研究从NumPy到BLAS的抽象抽象层的情况下,我能够重现scipy.linalg.blas.ddot
中的差异,因此我假设对BLAS中差异的解释也解释了NumPy中的差异。具体来说,请考虑以下示例:
import numpy as np
from scipy.linalg.blas import ddot
u = np.array([0.13463703107579461093,-0.07773272613450200874,-0.98784132994666418170])
v = np.array([-0.86246572448831815283,-0.03715105562531360872,-0.50475010960748223354])
a = np.dot(v,u)
b = v[0]*u[0] + v[1]*u[1] + v[2]*u[2]
c = ddot(v,u)
print(f'{a:.25f}')
print(f'{b:.25f}')
print(f'{c:.25f}')
这将产生以下输出:
Machine 1 Machine 2
a 0.3853810478481685120044631 0.3853810478481685675156143
b 0.3853810478481685120044631 0.3853810478481685120044631
c 0.3853810478481685120044631 0.3853810478481685675156143
类似地,以下Cython引起了相同的差异:
cimport scipy.linalg.cython_blas
cimport numpy as np
import numpy as np
cdef np.float64_t run_test(np.double_t[:] a,np.double_t[:] b):
cdef int ix,iy,n
ix = iy = 1
n = 3
return scipy.linalg.cython_blas.ddot(&n,&a[0],&ix,&b[0],&iy)
a = np.array([0.13463703107579461093,-0.98784132994666418170])
b = np.array([-0.86246572448831815283,-0.50475010960748223354])
print(f'{run_test(a,b):.25f}')
所以,我试图了解可能导致这种情况的原因。
有问题的计算机分别运行Windows 10(Intel(R)Core(TM)i7-5600U)和Windows Server 2016(Intel(R)Xeon(R)Gold 6140)。
在这两种情况下,我都只设置了numpy
,scipy
,cython
及其相关性,而没有设置新的conda环境。我已经在环境上运行了校验和,以确保最终包含的二进制文件达成一致并验证np.__config__.show()
的输出是否匹配。同样,我检查了mkl.get_version_string()
的输出在两台计算机上是否一致。
这使我认为问题可能出在硬件差异上。我没有研究最终将执行什么指令(缺少在Windows / MSVC上调试Cython代码的直接方法),但是我checked这两台机器都支持AVX2 / fma,这似乎可能是一个来源的差异。
另一方面,我确实发现这两台机器支持不同的指令集。具体地
Machine 1 (i7) Machine 2 (Xeon)
AVX Y Y
AVX2 Y Y
AVX512CD N Y
AVX512ER N N
AVX512F N Y
AVX512PF N N
fma Y Y
但是,我不知道一种确定它本身是否足以解释差异的好方法,或者它是否是红色鲱鱼(?)
所以我的问题变成:
从上面开始,有什么自然的步骤可以尝试找出导致差异的原因?是组装时间,还是还有其他更明显的东西?