最佳答案
关于类型化内存视图的 Cython 文档列出了三种赋值类型化内存视图的方法:
np.ndarray
和cython.view.array
。假设我没有从外部传入到 cython 函数中的数据,而是想分配内存并将其作为 np.ndarray
返回,那么我应该选择哪个选项?还要假设该缓冲区的大小不是编译时常量,也就是说,我不能在堆栈上分配,但是在选项1中需要 malloc
。
因此,这3个选项大致如下:
from libc.stdlib cimport malloc, free
cimport numpy as np
from cython cimport view
np.import_array()
def memview_malloc(int N):
cdef int * m = <int *>malloc(N * sizeof(int))
cdef int[::1] b = <int[:N]>m
free(<void *>m)
def memview_ndarray(int N):
cdef int[::1] b = np.empty(N, dtype=np.int32)
def memview_cyarray(int N):
cdef int[::1] b = view.array(shape=(N,), itemsize=sizeof(int), format="i")
令我惊讶的是,在这三种情况下,Cython 生成了相当多的代码用于内存分配,尤其是对 __Pyx_PyObject_to_MemoryviewSlice_dc_int
的调用。这表明(这里我可能错了,我对 Cython 内部工作原理的了解非常有限)它首先创建一个 Python 对象,然后将其“强制转换”到内存视图中,这似乎是不必要的开销。
简单的基准并没有显示出这三种方法之间有多大的差别,其中2种方法是最快的,但差距很小。
这三种方法中哪一种是推荐的? 还是有一种不同的、更好的选择?
后续问题: 在函数中处理了内存视图之后,我想最终以 np.ndarray
的形式返回结果。类型化内存视图是最好的选择,还是我宁愿首先使用以下旧的缓冲区接口来创建 ndarray
?
cdef np.ndarray[DTYPE_t, ndim=1] b = np.empty(N, dtype=np.int32)