如何在 Cython 中获得内存视图列表?

Hyr*_*ial 1 python cython memoryview

我的函数接受不同大小的 numpy 数组的列表:

def function1(list list_of_numpy_arrays):

现在我正在做:

cdef int[:] a_view = list_of_numpy_arrays[index]

问题是我必须多次索引列表,因此开销大大增加了时间(10 倍)。我正在寻找类似cdef int[:] a[5]可以拥有内存视图数组的东西,这样我就可以避免索引 python 列表的开销。

如果有解决方案,我还可以传递一个列表列表。

def function2(list list_of_lists):

Dav*_*idW 5

你所追求的在 Cython 中是不可能的。如果您想要性能良好的东西,我可能会创建一个包含内存视图中相关信息的 C 结构,然后使用它。这不是一个非常优雅的解决方案,但它会提供与使用内存视图类似的性能;我不建议将其设为一种常见模式,但如果您遇到数据需要的一次性问题,那么也没关系。

cdef struct FakeMemoryView:
    int* data
    int stride
    int length
Run Code Online (Sandbox Code Playgroud)

如果您准备强制 C 连续记忆视图 ( int[::1]) 那么您可以放弃,stride因为它会被认为是一个。可以使用 来对数据建立索引var.data[i*var.stride]。在函数开始时,您循环遍历 Python 列表以创建这些FakeMemoryViews 的数组,然后从那时起您只需使用此数组:

def function1(list list_of_numpy_arrays):
    assert len(list_of_numpy_arrays) == 5

    cdef FakeMemoryView new_list[5]

    # initialize the list
    cdef int[:] mview
    for i in range(5):
        mview = list_of_numpy_arrays[i]
        new_list[i].data = &mview[0]
        new_list[i].stride = mview.strides[0]
        new_list[i].length = mview.shape[0]

    # example access - zero the first lot of data
    for i in range(new_list[0].length):
        new_list[0].data[i*new_list[0].stride] = 0
Run Code Online (Sandbox Code Playgroud)

malloc如果您事先不知道列表的长度,那么您需要使用和自行处理内存free

此解决方案不处理 Numpy 数组的引用计数 - 因此您不应允许在持有 s 时释放 Numpy 数组FakeMemoryView。不要将数组存储为多个函数调用,也不要开始从输入列表中删除数组。