考虑以下Cython代码:
cimport cython
cimport numpy as np
import numpy as np
@cython.boundscheck(False)
@cython.wraparound(False)
def test_memoryview(double[:] a, double[:] b):
cdef int i
for i in range(a.shape[0]):
a[i] += b[i]
@cython.boundscheck(False)
@cython.wraparound(False)
def test_numpy(np.ndarray[double, ndim=1] a, np.ndarray[double, ndim=1] b):
cdef int i
for i in range(a.shape[0]):
a[i] += b[i]
def test_numpyvec(a, b):
a += b
def gendata(nb=40000000):
a = np.random.random(nb)
b = np.random.random(nb)
return a, b
在解释器中运行它几次(以便缓存预热)会产生以下结果:
In [14]: %timeit -n 100 test_memoryview(a, b)
100 loops, best of 3: 148 ms per loop
In [15]: %timeit -n 100 test_numpy(a, b)
100 loops, best of 3: 159 ms per loop
In [16]: %timeit -n 100 test_numpyvec(a, b)
100 loops, best of 3: 124 ms per loop
# See answer below :
In [17]: %timeit -n 100 test_raw_pointers(a, b)
100 loops, best of 3: 129 ms per loop
我尝试使用不同的数据集大小,结果发现向量化的NumPy函数比编译后的Cython代码更快,而我本来期望Cython在性能方面与向量化的NumPy相当。
我是否忘记了在Cython代码中进行优化?NumPy是否使用了某些东西(如BLAS),以使这样的简单操作运行得更快?我能否改进此代码的性能?
更新:原始指针版本似乎与NumPy相当。因此,使用内存视图或NumPy索引存在一些开销。
range
的使用转换成C循环,难道我错了吗? - F.X.double
时运行速度可能比纯C/Cython实现快两倍,使用float
时可能快四倍。请注意,具体的加速效果取决于您的硬件和numpy版本。 - Jaime