Python cython Memory查看速度比预期慢
我已经开始使用cython中的MemoryView来访问numpy阵列。它们的一个优点是比旧的numpy缓冲区支持快得多: 然而,我有一个例子,旧的numpy缓冲区支持比memoryView更快! 这怎么可能?!我想知道我是否正确使用了MemoryView 这是我的测试:Python cython Memory查看速度比预期慢,python,numpy,cython,memoryview,Python,Numpy,Cython,Memoryview,我已经开始使用cython中的MemoryView来访问numpy阵列。它们的一个优点是比旧的numpy缓冲区支持快得多: 然而,我有一个例子,旧的numpy缓冲区支持比memoryView更快! 这怎么可能?!我想知道我是否正确使用了MemoryView 这是我的测试: import numpy as np cimport numpy as np cimport cython @cython.boundscheck(False) @cython.wraparound(False) cpde
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
将numpy导入为np
cimport numpy作为np
西姆波特赛顿酒店
@cython.boundscheck(错误)
@cython.wrapparound(假)
cpdef np.ndarray[np.uint8_t,ndim=2]图像框1(np.ndarray[np.uint8_t,ndim=2]im,
np.ndarray[np.float64_t,ndim=1]pd,
整数框(半个大小):
cdef无符号整数p0=(pd[0]+0.5)
cdef无符号整数p1=(pd[1]+0.5)
cdef unsigned int top=p1-方框大小
cdef unsigned int left=p0-框大小
cdef unsigned int bottom=p1+方框大小的一半
cdef unsigned int right=p0+方框大小
cdef np.ndarray[np.uint8_t,ndim=2]框=im[顶部:底部,左侧:右侧]
返回框
@cython.boundscheck(错误)
@cython.wrapparound(假)
cpdef np.uint8_t[:,::1]图像框2(np.uint8_t[:,::1]im,
np.64_t[:]pd,
整数框(半个大小):
cdef无符号整数p0=(pd[0]+0.5)
cdef无符号整数p1=(pd[1]+0.5)
cdef unsigned int top=p1-方框大小
cdef unsigned int left=p0-框大小
cdef unsigned int bottom=p1+方框大小的一半
cdef unsigned int right=p0+方框大小
cdef np.uint8_t[:,::1]框=im[上:下,左:右]
返回框
计时结果如下:
图像_框1:键入的numpy:
100000个回路,最好3个:每个回路11.2 us
图2:内存视图:
100000个回路,最好的3个:每个回路18.1 us
这些测量是在IPython上使用%timeit image_box1(im、pd、box_一半大小)好的!我发现了问题。 正如seberg指出的,memoryview的速度似乎较慢,因为测量包括从numpy数组到memoryview的自动转换 我使用以下函数从cython模块中测量时间:
def test(params):
import timeit
im = params[0]
pd = params[1]
box_half_size = params[2]
t1 = timeit.Timer(lambda: image_box1(im, pd, box_half_size))
print 'image_box1: typed numpy:'
print min(t1.repeat(3, 10))
cdef np.uint8_t[:, ::1] im2 = im
cdef np.float64_t[:] pd2 = pd
t2 = timeit.Timer(lambda: image_box2(im2, pd2, box_half_size))
print 'image_box2: memoryview:'
print min(t2.repeat(3, 10))
结果:
图像_框1:键入的numpy:
9.07607864065e-05
图2:内存视图:
5.81799904467e-05
所以记忆视图确实更快
请注意,在调用image_box2之前,我将im和pd转换为MemoryView。如果我不执行此步骤,直接传递im和pd,则image_box2会变慢:
图像_框1:键入的numpy:
9.12262257771e-05
图2:内存视图:
0.000185245087778我想您是在用python对这些函数计时?从那时起,返回值也是第二个函数中的一个
np.ndarray
(我假设),这可能已经解释了速度减慢的原因,因为制作np.ndarray
是一项额外的工作,总体上没有太多的工作要做。是的,我从IPython使用命令:%timeit image\u box1(im,pd,box\u半个大小)我刚刚编辑了我的问题,将cython中的计时功能包括在内。记忆视图仍然比较慢!校正你说得对,延迟是从numpy数组到memoryview的转换!我不确定这是否又是100%公平的,因为如果您键入,您可能还应该在cython中键入数组。但我想在任何情况下,它归结为一些转换(数组->memoryview或memoryview->数组),但无论如何,这都是很小的开销。根据你的建议,我尝试通过将im和pd复制到相应的numpy缓冲区类型来使测试更公平。我在test函数中执行此操作,然后将缓冲区类型传递给image_box1。然而,如果我试图将这些缓冲区类型传递给image_box1,我会得到编译错误“缓冲区类型仅允许作为函数局部变量”,我一直在试图找到该错误的解决方案,但似乎没有找到任何解决方案。我开始认为这是赛昂的限制。