以类型化 memoryview 作为成员的结构定义
Posted
技术标签:
【中文标题】以类型化 memoryview 作为成员的结构定义【英文标题】:Struct definition with typed memoryview as member 【发布时间】:2014-01-31 14:43:41 【问题描述】:目前,我正在尝试使具有类型化 memoryview 的结构工作。例如
ctypedef struct node:
unsigned int[:] inds
如果 inds 不是 memoryview,就我所见,它可以完美地工作。但是,使用 memoryview 并使用类似
def testFunction():
cdef node testNode
testNode.inds = numpy.ones(3,dtype=numpy.uint32)
我收到分段错误。是否有什么明显的我忽略了,或者类型化的内存视图在结构中不起作用?
编辑:
所以我稍微重写了示例(由于 larsman 的问题),希望能稍微澄清一下问题:
def testFunction():
cdef node testNode
cdef unsigned int[:] tempInds
tempInds = numpy.ones(3,dtype=numpy.uintc)
testNode.inds = tempInds
只有最后一行会产生段错误。我不知道如何更详细地检查问题。对我来说,目前看起来结构无法处理类型化的内存视图......但希望我遗漏了一些东西。
我正在使用 Cython 0.20(刚刚更新,之前的 0.19 给出了相同的错误)。也将 Numpy 更新到 1.8.0。
编辑 2:
如果以后有类似问题的人读到这个:我现在搜索了很多,但无法让它工作。由于除了内存视图之外的其他一切都在工作,我想这是不可能的(很容易)。 由于多维数组的方便切片,我打算使用内存视图,但显然它们在结构中不起作用。现在,我在结构中保存了一个 C 指针,如果需要切片,将它们转换为内存视图......必须非常小心地正确访问数组,但在我的情况下它似乎可以工作。如果从现在开始的几周内此线程中没有解决答案,我可能会为 Cython 提出功能请求。
【问题讨论】:
这个段错误的哪一部分,你有哪个 Cython 版本? (顺便说一句,unsigned int
对应于np.uintc
,不一定是uint32
。)
我可能应该知道 uintc。谢谢你的提示。我在原始帖子中添加了一些东西。如果您有任何想法,我可以尝试,我很乐意听到。
【参考方案1】:
问题来自未初始化的内存,因为 Cython 缺少原始 cdefed 结构的构造函数。当进行 testNode.inds = tempInds 分配时,Cython 会尝试释放甚至没有正确初始化的 testNode.inds 并取消引用随机指针。
这确实是 Cython 中的错误(请归档!)并且目前没有解决方案(据我所知),但这是一个有效的丑陋 hack。
from libc.string cimport memset
ctypedef struct node:
int dummy_hack
unsigned int[:] inds
def testFunction():
cdef node testNode
cdef unsigned int[:] tempInds
tempInds = numpy.ones(3,dtype=numpy.uintc)
# zero init memory to avoid deref garbage
memset(&testNode.dummy_hack, 0, sizeof(void*)*4)
testNode.inds = tempInds
仅供参考。 C++ 中的实际内存视图对象如下所示(在 Cython 21.2 上):
MemoryView object is
__Pyx_memviewslice struct typedef struct
struct __pyx_memoryview_obj *memview;
char *data;
Py_ssize_t shape[8];
Py_ssize_t strides[8];
Py_ssize_t suboffsets[8];
;
【讨论】:
你的hack的这个问题是它最终会泄漏内存(memoryview在其生命结束时不会被正确破坏)。不过,您可以正确识别问题。以上是关于以类型化 memoryview 作为成员的结构定义的主要内容,如果未能解决你的问题,请参考以下文章