如何在 Cython 中获得内存视图列表?
How to have a list of memory views in Cython?
我的函数接收不同大小的 numpy 数组列表:
def function1(list list_of_numpy_arrays):
现在我在做:
cdef int[:] a_view = list_of_numpy_arrays[index]
问题是我必须多次索引列表,因此开销大大增加了时间 (10x)。我正在寻找类似 cdef int[:] a[5]
的东西,在那里我可以有一个内存视图数组,这样我就可以避免索引 python 列表的开销。
如果有解决方案,我也可以传入列表列表。
def function2(list list_of_lists):
你所追求的在 Cython 中是不可能实现的。如果您想要性能良好的东西,我可能会创建一个包含来自内存视图的相关信息的 C 结构,然后改用它。这不是一个非常优雅的解决方案,但它会提供与使用内存视图相似的性能;我不建议将其设为通用模式,但如果您遇到 one-off 数据需要的问题,那没关系。
cdef struct FakeMemoryView:
int* data
int stride
int length
如果您准备强制使用 C 连续内存视图 (int[::1]
),那么您可以放弃 stride
,因为众所周知它是一个。可以使用 var.data[i*var.stride]
对数据进行索引。在您的函数开始时,您循环遍历 Python 列表以创建这些 FakeMemoryView
的数组,然后从那时起您只需使用此数组:
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
如果你事先不知道列表的长度,那么你需要自己用malloc
和free
来处理内存。
此解决方案不处理 reference-counting Numpy 数组 - 因此您不应允许在持有 FakeMemoryView
时释放 Numpy 数组。不要为多个函数调用存储数组,也不要开始从输入列表中删除数组。
我的函数接收不同大小的 numpy 数组列表:
def function1(list list_of_numpy_arrays):
现在我在做:
cdef int[:] a_view = list_of_numpy_arrays[index]
问题是我必须多次索引列表,因此开销大大增加了时间 (10x)。我正在寻找类似 cdef int[:] a[5]
的东西,在那里我可以有一个内存视图数组,这样我就可以避免索引 python 列表的开销。
如果有解决方案,我也可以传入列表列表。
def function2(list list_of_lists):
你所追求的在 Cython 中是不可能实现的。如果您想要性能良好的东西,我可能会创建一个包含来自内存视图的相关信息的 C 结构,然后改用它。这不是一个非常优雅的解决方案,但它会提供与使用内存视图相似的性能;我不建议将其设为通用模式,但如果您遇到 one-off 数据需要的问题,那没关系。
cdef struct FakeMemoryView:
int* data
int stride
int length
如果您准备强制使用 C 连续内存视图 (int[::1]
),那么您可以放弃 stride
,因为众所周知它是一个。可以使用 var.data[i*var.stride]
对数据进行索引。在您的函数开始时,您循环遍历 Python 列表以创建这些 FakeMemoryView
的数组,然后从那时起您只需使用此数组:
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
如果你事先不知道列表的长度,那么你需要自己用malloc
和free
来处理内存。
此解决方案不处理 reference-counting Numpy 数组 - 因此您不应允许在持有 FakeMemoryView
时释放 Numpy 数组。不要为多个函数调用存储数组,也不要开始从输入列表中删除数组。