python - Cython 中动态数组的 2D MemoryView
问题描述
我知道这个问题,但我一直在寻找一种更简单的方法来从 C 数组生成 2d 内存视图。由于我是 C 和 Cython noobie,有人可以解释一下为什么像
cdef int[:, :] get_zeros(int d):
# get 2-row array of zeros with d as second dimension
cdef int i
cdef int *arr = <int *> malloc(sizeof(int) * d)
for i in range(d):
arr[i] = 0
cdef int[:, :] arr_view
arr_view[0, :] = <int[:d]>arr
arr_view[1, :] = <int[:d]>arr
return arr_view
不行吗?
编译时我得到Cannot assign type 'int[::1]' to 'int'
错误。这是否意味着 2d memview 被第一个 assign 语句折叠到 1d 或者是因为 memoryviews 需要连续块等?
解决方案
显然很难“解释为什么某些东西 [...] 不起作用”,因为最终这只是一个设计决策,可以采取不同的方式。但:
Cython 内存视图被设计为非常愚蠢。他们所做的只是提供一些很好的语法来访问实现Python 缓冲区协议的东西的内存,然后有一点额外的语法让你做一些事情,比如获取指针的 1D 内存视图。
此外,内存视图作为一个整体包装了一些东西。当你创建cdef int[:, :] arr_view
它是无效的,直到你这样做arr_view = something
。尝试分配它的一部分是无稽之谈,因为(a)它会将分配委托给它使用缓冲区协议包装的东西,并且(b)分配的确切工作方式取决于您包装的缓冲区协议的格式. 如果包装一个“间接”缓冲区协议对象,你所做的可能是有效的,但如果包装一个连续的数组则没有意义。由于arr_view
可以包装 Cython 编译器必须将其视为错误。
您链接到的问题实现了缓冲区协议,因此是实现这种数组的正确方法。您正在尝试做的是采用额外的语法,从指针中提供 1D 内存视图,并将其强制转换为 2D 内存视图的一部分,模糊地希望这可能会起作用。这需要很多逻辑,远远超出了 Cython 内存视图的设计范围。
可能还有几点值得说明:
指针的内存视图不处理指针的释放(因为它们几乎不可能事后猜测你想要什么)。你必须处理这个逻辑。如果有效,您当前的设计会泄漏内存。在您链接到包装类的设计中,可以实现这一点
__dealloc__
(尽管该答案中没有显示),因此效果更好。我个人的观点是“参差不齐的数组”(指向指针的二维数组)很糟糕。它们需要大量的分配和释放。有很多机会对它们进行半初始化。访问它们需要几个间接级别,因此速度很慢。唯一对他们有用的是它们
arr[idx1][idx2]
在 C 中提供了一种语法。总的来说,我更喜欢 Numpy 分配一维数组并使用形状/步幅来确定索引位置的方法。(显然,如果您要包装现有库,那么您可能不是您的选择......)
推荐阅读
- react-native - 需要未知模块“3”
- python - 使用掩码中的轮廓从原始图像中获取 ROI 的有效方法
- html - Arraylist 到 html 表
- angular - Angular 中的响应无法读取 API 响应中未定义的属性
- angular - 根据函数的参数创建对象
- javascript - React Native 导航中全屏模式的“无法读取未定义的属性导航”
- r - Ubuntu AWS 和 Ubuntu 笔记本电脑中 R 程序的不同行为
- python - Python:使用循环遍历电子表格的一列,将其插入 url,然后保存数据
- assembly - 我有一个问题要求使用 MARS 4.5 模拟器使用 MIPS 汇编语言反转数组
- excel - 为什么有时一行代码可以工作但下一行代码不行