Cython代码中提供了cdef type [:] 的写法,那么cdef int [:]到底是什么意思呢?
Memoryview切片
Cython 0.16中,增加了记忆体视图(memoryview),用它可以很方便地存取NumPy等buffer层面的中的资料。
Memoryview切片(Memoryview slices)是Cython中的一种特殊类型,通过它可以高效地访问支持buffer的Python实例内部的资料区,例如NumPy中的ndarray。下面我们通过一个例子说明它的用法
def memview_sum(int[:] a):
# 参数a是一个一维整数切片类型,可以将与此切片类型一致的矩阵传递给它
cdef int i
cdef int s = 0
# 和NumPy矩阵一样,它的shape属性为其各个轴的长度
for i in range(a.shape[0]):
s += a[i]
return s
用法
参考官方文档
为了获得额外的速度提升,如果您知道您提供的 NumPy 数组在内存中是连续的,您可以将 memoryview 声明为连续的。
我们给出了一个 3 维数组的例子。如果你想给 Cython 数据是 C-contiguous 的信息,你必须像这样声明 memoryview:
cdef int [:,:,::1] a
如果你想给 Cython 数据是 Fortran 连续的信息,你必须像这样声明 memoryview:
cdef int [::1, :, :] a
如果所有这些对您来说都没有意义,您可以跳过这一部分,将数组声明为连续会限制函数的使用,因为它拒绝将数组切片作为输入。如果您仍然想了解什么是连续数组,您可以在 StackOverflow 上看到这个答案。
为了给出数字,以下是通过将 memoryviews 声明为连续而应该获得的速度提升:
In [23]: %timeit compute_contiguous.compute(array_1, array_2, a, b, c)
11.1 ms ± 30.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我们现在比 NumPy 版本快 9 倍左右,比纯 Python 版本快 6300 倍!