我开始在Cython中使用memoryviews来访问NumPy数组。它们有很多优点,其中一个是比旧的NumPy缓冲区支持要快得多:
http://docs.cython.org/src/userguide/memoryviews.html#comparison-to-the-old-buffer-support
然而,在我的一个例子中,旧的NumPy缓冲区支持比memoryviews更快!这怎么可能?我想知道我是否正确地使用了memoryviews?
这是我的测试:
这是我的测试:
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef np.ndarray[np.uint8_t, ndim=2] image_box1(np.ndarray[np.uint8_t, ndim=2] im,
np.ndarray[np.float64_t, ndim=1] pd,
int box_half_size):
cdef unsigned int p0 = <int>(pd[0] + 0.5)
cdef unsigned int p1 = <int>(pd[1] + 0.5)
cdef unsigned int top = p1 - box_half_size
cdef unsigned int left = p0 - box_half_size
cdef unsigned int bottom = p1 + box_half_size
cdef unsigned int right = p0 + box_half_size
cdef np.ndarray[np.uint8_t, ndim=2] box = im[top:bottom, left:right]
return box
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef np.uint8_t[:, ::1] image_box2(np.uint8_t[:, ::1] im,
np.float64_t[:] pd,
int box_half_size):
cdef unsigned int p0 = <int>(pd[0] + 0.5)
cdef unsigned int p1 = <int>(pd[1] + 0.5)
cdef unsigned int top = p1 - box_half_size
cdef unsigned int left = p0 - box_half_size
cdef unsigned int bottom = p1 + box_half_size
cdef unsigned int right = p0 + box_half_size
cdef np.uint8_t[:, ::1] box = im[top:bottom, left:right]
return box
时间测试结果如下:
image_box1:使用numpy: 100000次循环,3次最佳结果:每次循环耗时11.2微秒
image_box2:使用memoryview: 100000次循环,3次最佳结果:每次循环耗时18.1微秒
这些测量是在IPython中使用%timeit image_box1(im, pd, box_half_size)进行的。
np.ndarray
(我猜),这可能已经解释了减速的原因,因为制作np.ndarray
需要一些额外的工作,在这里整体上没有做太多事情。 - seberg