Jér*_*ard 8
问题来自np.convolve
. 这是一个已知问题。事实证明,当前的 Numba 实现比 Numpy 的实现要慢得多 (在 Windows 上测试的版本 <=0.54.1)。
在引擎盖下
一方面,Numpy 实现调用correlate
本身执行一个点积,应该由系统上可用的快速 BLAS 库实现。另一方面,使用它的Numba实现调用_get_inner_prod
也应该使用相同的 BLAS 库(假设检测到 BLAS 应该是这种情况)......np.dot
话虽如此,与点积相关的问题有很多:
首先,如果内部变量_HAVE_BLAS
ofnumba/np/arraymath.py
被手动禁用,Numba 会使用点积的后备实现,它应该会显着变慢。然而,事实证明,使用 by 使用的后备点积实现np.convolve
比在我的机器上使用 BLAS 包装器的执行速度快 5 倍!fastmath=True
另外使用 Numba 装饰器中的参数njit
会导致整体执行速度提高 8.7 倍!这是测试代码:
import numpy as np
import numba as nb
def npConvolve(a, b):
return np.convolve(a, b)
@nb.njit('float64[:](float64[:], float64[:])')
def nbConvolveUncont(a, b):
return np.convolve(a, b)
@nb.njit('float64[::1](float64[::1], float64[::1])')
def nbConvolveCont(a, b):
return np.convolve(a, b)
a = np.random.random(6400)
b = np.random.random(65)
%timeit -n 100 npConvolve(a, b)
%timeit -n 100 nbConvolveUncont(a, b)
%timeit -n 100 nbConvolveCont(a, b)
以下是原始有趣的结果:
With _HAVE_BLAS=True (default):
126 µs ± 292 ns per loop
1.6 ms ± 21.3 µs per loop
1.6 ms ± 18.5 µs per loop
With _HAVE_BLAS=False:
125 µs ± 359 ns per loop
311 µs ± 1.18 µs per loop
268 µs ± 4.26 µs per loop
With _HAVE_BLAS=False and fastmath=True:
125 µs ± 757 ns per loop
327 µs ± 3.69 µs per loop
183 µs ± 654 ns per loop
此外,np_convolve
Numba 在内部翻转一些数组参数,然后使用具有非平凡步幅(即非 1)的翻转数组执行点积。这种不平凡的步幅可能会对点积性能产生影响。更一般地说,任何阻止编译器知道数组是连续的转换肯定会强烈影响性能。实际上,以下测试显示了使用 Numba 的点积实现处理连续数组的影响:
import numpy as np
import numba as nb
def np_dot(a, b):
return np.dot(a, b)
@nb.njit('float64(float64[::1], float64[::1])')
def nb_dot_cont(a, b):
return np.dot(a, b)
@nb.njit('float64(float64[::1], float64[:])')
def nb_dot_stride(a, b):
return np.dot(a, b)
v = np.random.random(128*1024)
%timeit -n 200 np_dot(v, v) # 36.5 µs ± 4.9 µs per loop
%timeit -n 200 nb_dot_stride(v, v) # 361.0 µs ± 17.1 µs per loop (x10 !!!)
%timeit -n 200 nb_dot_cont(v, v) # 34.1 µs ± 2.9 µs per loop
关于 Numpy 和 Numba 的一些一般说明
请注意,Numba 在处理非常大的数组时几乎无法加速 Numpy 调用,因为 Numba主要在 Python 中重新实现 Numpy 函数并使用JIT 编译器(LLVM-Lite) 来加速它们,而 Numpy 主要以普通方式实现 - C(带有相当慢的 Python 包装代码)。Numpy 代码使用SIMD 指令等低级处理器特性来加速许多函数的执行。两者似乎都使用已知高度优化的 BLAS 库。由于 Numpy 目前比 Numba 更成熟,因此 Numpy 通常会更加优化:Numpy 有更多的贡献者工作时间更长。
更多推荐
真的很,Numba,np,convolve
发布评论