对象成员的Cython缓冲区声明

时间:2012-01-10 18:09:01

标签: 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)

不幸的是,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

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

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

2 个答案:

答案 0 :(得分:13)

可以选择使用内存切片或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)

答案 1 :(得分:6)

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

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

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