Numpy 浮点非决定论的原因?包括努比?
IEEE浮点运算是确定性的,但整体浮点计算可能是非确定性的,请参见: 。。。就浮点计算的执行顺序而言,并行计算是不确定的,这可能导致跨运行的非位精确结果 问题分两部分:Numpy 浮点非决定论的原因?包括努比?,numpy,blas,intel-mkl,atlas,non-deterministic,Numpy,Blas,Intel Mkl,Atlas,Non Deterministic,IEEE浮点运算是确定性的,但整体浮点计算可能是非确定性的,请参见: 。。。就浮点计算的执行顺序而言,并行计算是不确定的,这可能导致跨运行的非位精确结果 问题分两部分: 除此之外,整个浮点计算怎么可能是非确定性的,产生不完全相等的结果 考虑一个调用NumPy、CVXOPT和SciPy子例程(如SciPy.optimize.fsolve())的单线程Python程序,这些子例程依次调用本机库(如MINPACK和GLPK)和优化线性代数子例程(如BLAS、ATLAS和MKL)。“” 这些本机库是否
- 除此之外,整个浮点计算怎么可能是非确定性的,产生不完全相等的结果
- 考虑一个调用NumPy、CVXOPT和SciPy子例程(如
)的单线程Python程序,这些子例程依次调用本机库(如MINPACK和GLPK)和优化线性代数子例程(如BLAS、ATLAS和MKL)。“” 这些本机库是否以引入非确定性结果的方式进行过并行化SciPy.optimize.fsolve()
- 相同的软件,相同的输入,在相同的硬件上。多次运行的输出应相等。
- 如果这是可行的,那么最好测试代码重构后的输出是否相等。(是的,对操作顺序的某些更改可能导致某些输出不相等。)
- 程序中的所有随机数都是psuedo随机数,在所有运行中以一致的方式使用相同的种子
- 没有未初始化的值。Python通常以这种方式是安全的,但是
在不初始化条目的情况下返回一个新数组。现在还不清楚它在实践中是否快得多。所以当心numpy.empty()
- @PaulPanzer的测试表明,
确实返回未初始化的数组,并且它可以轻松快速地回收最近的数组:numpy.empty()
将numpy导入为np 阿兰奇(100);np.空(100,int);np.empty(100,int) np.arange(100200.0);np.空(100,浮动);np.空(100,浮动)
- 为这些例程获取有用的计时度量是很棘手的!在
循环中,timeit
可以继续重新分配相同的一个或两个内存节点。时间与数组大小无关。为防止循环再造:numpy.empty()
但是将数组大小减少到从timeit导入timeit timeit('l.append(numpy.empty(100000))','import numpy;l=[])) timeit('l.append(numpy.zeros(100000)),'import numpy;l=[]))
需要15倍的时间;将其减少到numpy.zero(10000)
需要1.3倍的时间(在我的MBP上)。令人费解numpy.zero(1000)
- @PaulPanzer的测试表明,
MKL==2019.0
也会出现这些漏洞
看
也许我遇到的其余问题是由于其他链接到Accelerate的库造成的
注意:对于这个问题,我仍然有更多的答案。你可能会感兴趣,而且“在我的测量中,空()大约需要零()[…]的时间”,这要视情况而定。在频繁的dealloc/realloc(例如简单的
timeit
)empty
可以比零快几个数量级。empty
有一些有效的用法,排列的反转只是一个例子,只是一个简短的轶事。最近,我遇到了这个确切的问题,一些代码正在用C语言进行确定性最小化。在我认为应该只是一个表面上的改变之后,我得到了稍微不同的结果。原来问题是我把一行如a*=b/c
改成了a=a*b/c
,结果略有不同。由于这导致了一个稍有不同的结果,它导致最小值尝试了不同的下一个点,结果滚雪球般地扩大,因此我在两次提交之间得到了明显不同的结果。@palpanzer结果是numpy.empty()
正在将我的MBP上的数组归零。这就解释了时间的相似性。也许这是NumPy调用Apple的Accelerate框架的结果,该框架是默认框架,而不是openblas。我将用MKL重新测试。我的猜测是,zeros
调用calloc
和calloc
作为决定是否回收或请求新内存的人,确实会知道它是否必须自己进行调零,或者可以假设已经进行了调零。请注意,我不是受过训练的计算机科学家。