我在评估numpy中的表达式时发现了一个奇怪的性能差异。
我执行了以下代码:
import numpy as np
myarr = np.random.uniform(-1,1,[1100,1100])
然后
%timeit np.exp( - 0.5 * (myarr / 0.001)**2 )
>> 184 ms ± 301 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
和
%timeit np.exp( - 0.5 * (myarr / 0.1)**2 )
>> 12.3 ms ± 34.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
在第二种情况下,计算速度快了将近15倍!请注意,唯一的区别是系数为0.1或0.001。
这种行为的原因是什么?我能换点东西使第一次计算和第二次一样快吗?
最佳答案
使用Intel SVML
我没有使用Intel SVML的numexpr
工作,但是使用工作SVML的numexpr
应该和numba一样好。Numba
基准在没有SVML的情况下显示出完全相同的行为,但是在使用SVML时表现得更好。
代码
import numpy as np
import numba as nb
myarr = np.random.uniform(-1,1,[1100,1100])
@nb.njit(error_model="numpy",parallel=True)
def func(arr,div):
return np.exp( - 0.5 * (myarr / div)**2 )
计时
#Core i7 4771
#Windows 7 x64
#Anaconda Python 3.5.5
#Numba 0.41 (compilation overhead excluded)
func(myarr,0.1) -> 3.6ms
func(myarr,0.001) -> 3.8ms
#Numba (set NUMBA_DISABLE_INTEL_SVML=1), parallel=True
func(myarr,0.1) -> 5.19ms
func(myarr,0.001) -> 12.0ms
#Numba (set NUMBA_DISABLE_INTEL_SVML=1), parallel=False
func(myarr,0.1) -> 16.7ms
func(myarr,0.001) -> 63.2ms
#Numpy (1.13.3), set OMP_NUM_THREADS=4
np.exp( - 0.5 * (myarr / 0.001)**2 ) -> 70.82ms
np.exp( - 0.5 * (myarr / 0.1)**2 ) -> 12.58ms
#Numpy (1.13.3), set OMP_NUM_THREADS=1
np.exp( - 0.5 * (myarr / 0.001)**2 ) -> 189.4ms
np.exp( - 0.5 * (myarr / 0.1)**2 ) -> 17.4ms
#Numexpr (2.6.8), no SVML, parallel
ne.evaluate("exp( - 0.5 * (myarr / 0.001)**2 )") ->17.2ms
ne.evaluate("exp( - 0.5 * (myarr / 0.1)**2 )") ->4.38ms
#Numexpr (2.6.8), no SVML, single threaded
ne.evaluate("exp( - 0.5 * (myarr / 0.001)**2 )") ->50.85ms
ne.evaluate("exp( - 0.5 * (myarr / 0.1)**2 )") ->13.9ms