在迭代NumPy数组时,Numba似乎比Cython快得多。
我可能错过了哪些Cython优化?
这里是一个简单的例子:
纯Python代码:
import numpy as np
def f(arr):
res=np.zeros(len(arr))
for i in range(len(arr)):
res[i]=(arr[i])**2
return res
arr=np.random.rand(10000)
%timeit f(arr)
输出:每次循环的平均值为4.81毫秒,标准差为72.2微秒(基于7次运行,每次100个循环)
Jupyter中的Cython代码:
%load_ext cython
%%cython
import numpy as np
cimport numpy as np
cimport cython
from libc.math cimport pow
#@cython.boundscheck(False)
#@cython.wraparound(False)
cpdef f(double[:] arr):
cdef np.ndarray[dtype=np.double_t, ndim=1] res
res=np.zeros(len(arr),dtype=np.double)
cdef double[:] res_view=res
cdef int i
for i in range(len(arr)):
res_view[i]=pow(arr[i],2)
return res
arr=np.random.rand(10000)
%timeit f(arr)
输出: 每次循环445微秒 ± 5.49微秒 (7次运行的平均值±标准差, 每次循环1000次)
Numba代码:
import numpy as np
import numba as nb
@nb.jit(nb.float64[:](nb.float64[:]))
def f(arr):
res=np.zeros(len(arr))
for i in range(len(arr)):
res[i]=(arr[i])**2
return res
arr=np.random.rand(10000)
%timeit f(arr)
Out: 本例中,Numba比Cython快近50倍。作为一个Cython初学者,我猜我错过了什么。
在这种简单的情况下,使用NumPy的向量化函数square
会更加合适。%timeit np.square(arr)
输出:每个循环5.75微秒,标准偏差为78.9纳秒(7次运行的平均值±标准偏差,每次100,000次循环)
pow(arr[i],2)
会将数字2
视为float类型,从而使计算变得更加复杂。 - Antonio Ragagnin