首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Cython中来自动态数组的2D MemoryView

Cython中来自动态数组的2D MemoryView
EN

Stack Overflow用户
提问于 2019-10-30 11:09:14
回答 2查看 1.1K关注 0票数 1

我知道这个问题,但我正在寻找一种从C数组生成2d内存视图的更简单的方法。既然我是C和Cython noobie,谁能解释一下为什么

代码语言:javascript
运行
复制
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'作为错误。这是否意味着第一个赋值语句对1d折叠了2d memview,还是因为内存视图需要连续块等等?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-31 11:01:53

很明显,很难“解释为什么某件事情.不起作用”,因为最终这只是一个可以采取不同方式的设计决策。但是:

Cython内存视图被设计成相当愚蠢。他们所做的就是提供一些很好的语法来访问实现Python缓冲协议的东西的内存,然后有一些额外的语法让您可以得到指针的一维内存视图。

此外,内存视图作为一个整体包装了一些东西。创建cdef int[:, :] arr_view时,在执行arr_view = something之前它是无效的。试图分配给它的一部分是无稽之谈,因为(a)它将分配委托给它使用缓冲区协议包装的东西,(b)分配的确切方式将取决于您包装的缓冲区协议的格式。如果包装一个“间接”缓冲区协议对象,您所做的工作可能是有效的,但是如果包装一个连续的数组,则没有意义。由于arr_view可能正在包装,所以Cython编译器必须将其视为一个错误。

你所链接到的问题实现了缓冲协议,因此是实现这种数组的正确方法。你想要做的是从指针中获得一个一维内存视图的额外语法,并将它强制进入一个2D内存视图的一部分,从而模糊地希望这可能会奏效。这需要大量的逻辑,这些逻辑远远超出了Cython内存视图设计的范围。

也许还有几点值得提出来:

  • 指针的内存视图不处理指针的释放(因为它们几乎不可能事后猜测您想要什么)。你得处理好这个逻辑。您当前的设计将泄漏内存,如果它有效的话。在设计中,链接到包装类可以在__dealloc__中实现这一点(尽管答案中没有显示),因此更好。
  • 我个人的观点是,“粗糙数组”(指向指针的二维指针数组)是可怕的。它们需要大量的分配和取消分配。有很多机会让他们半途而废。访问它们需要两个级别的间接,因此是缓慢的。唯一适合它们的是,它们在C中提供了arr[idx1][idx2]语法。一般来说,我更喜欢Numpy的方法,它分配一维数组,并使用for /量程来确定索引的位置。(显然,如果您正在包装一个现有的库,那么您可能不是您的选择.)
票数 2
EN

Stack Overflow用户

发布于 2019-10-31 21:21:50

除了@DavidW提供的精彩答案之外,我还想添加一些更多的信息。在您包含的代码中,我看到您正在malloc-正在处理一个In数组,然后在for-循环中将内容归零。一种更方便的方法是使用C的calloc函数,它保证指向零内存的指针,之后不需要for循环。

此外,您还可以创建一个int *,它指向一个数据的“数组”,该数组的总大小为2*d* size of (Int)。这将确保数据的“行”彼此相连,而不是分开和粗糙。然后可以直接将其转换到2d内存视图中。

正如注释中所承诺的,下面是转换代码的样子(包括calloc的使用):

代码语言:javascript
运行
复制
cdef int[:, :] get_zeros(int d):    
    cdef int *arr = <int *>calloc(2 * d, sizeof(int))
    cdef int[:, :] arr_view = <int[:2, :d]>arr
    return arr_view

如果您想尝试一下,每个文档的python中似乎也有一个钙当量。但是,它似乎没有被包装。在cython的mem.pxd模块中,这就是为什么您可能找不到它的原因。您可以在代码中声明一个类似的extern块来包装它,就像包含在该链接中的其他函数一样。

如果您想了解更多关于编写分配器以从大块中分配内存的知识,下面是一个奖金环节 (例如,PyMem_*函数可能在幕后做什么,但在特定用例的可调和控制下)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58624047

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档