以类型化 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 作为成员的结构定义的主要内容,如果未能解决你的问题,请参考以下文章

C语言数据类型——结构体

C语言数据类型——结构体

数据结构 -- 结构体Struct

Go语言学习之旅--结构体

Go语言学习之旅--结构体

Go语言学习之旅--结构体