Cython中cdef int [:]的作用

本文解释了Cython中的cdefint[:]切片概念,探讨了如何利用Memoryview高效访问NumPy数组。通过实例展示了连续内存视图声明对速度提升的影响,并提到了不同连续数组声明的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 倍!