对象成员的Cython缓冲区声明

Bre*_*nor 22 python numpy cython

我想拥有一个带有NumPy成员的Cython"cdef"对象,并且能够使用快速缓冲区访问.理想情况下,我会做类似的事情:

import numpy as np
cimport numpy as np

cdef class Model:
  cdef np.ndarray[np.int_t, ndim=1] A

  def sum(self):
    cdef int i, s=0, N=len(self.A)
    for 0 <= i < N:
      s += self.A[i]
    return s

  def __init__(self):
    self.A = np.arange(1000)
Run Code Online (Sandbox Code Playgroud)

不幸的是,Cython无法编译这个错误Buffer types only allowed as function local variables.

我正在使用的解决方法是在分配给对象成员的新局部变量上声明缓冲区属性:

cdef class Model:
  cdef np.ndarray A

  def sum(self):
    cdef int i, s=0, N=len(self.A)
    cdef np.ndarray[np.int_t, ndim=1] A = self.A
    for 0 <= i < N:
      s += A[i]
    return s
Run Code Online (Sandbox Code Playgroud)

如果你想让多个方法访问相同的数据结构,这变得非常烦人 - 这似乎是一个非常常见的用例,不是吗?

有没有更好的解决方案,不需要在每个方法中重新声明类型?

fco*_*fco 14

可以选择使用内存片或cython数组 http://docs.cython.org/src/userguide/memoryviews.html

import numpy as np
cimport numpy as np

  cdef class Model:

    cdef int [:] A

    def sum(self):

        for 0 <= i < N:
            s += self.A[i]
        return s

    def __init__(self):
        self.A = np.arange(1000)
Run Code Online (Sandbox Code Playgroud)


Jos*_*del 6

您当前使用的解决方案是我倾向于使用的解决方案,即在函数中创建本地副本.它并不优雅,但我认为你没有受到巨大的性能打击(或者至少在我的情况下,我在这个方法上做了很多工作,因此它没有明显的区别).我还在__cinit__方法中创建了一个C数组,然后用__init__中的数据填充它(确保使用__dealloc__来正确清理).你失去了numpy数组的一些功能,但你仍然可以像使用c-array一样使用它.

您还可以查看cython列表中这封旧电子邮件中的讨论:

http://codespeak.net/pipermail/cython-dev/2009-April/005214.html

  • 更新链接http://www.mail-archive.com/cython-dev@codespeak.net/msg05166.html (2认同)