Cython对象成员的缓冲区声明
我想创建一个Cython的“cdef”对象,里面有一个NumPy成员,并且能够快速访问这个成员的数据。理想情况下,我想做的事情是这样的:
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无法编译这个代码,会报错说 只允许将缓冲区类型作为函数局部变量
。
我现在的解决办法是,在一个新的局部变量中声明缓冲区属性,并把它赋值给对象的成员:
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 个回答
6
你现在用的解决方案就是我通常会用的,也就是在函数里做一个本地的副本。这种做法虽然不算优雅,但我觉得对性能影响不大(至少在我的情况下,我在这个方法里做了很多工作,所以没什么明显的差别)。我还在 __cinit__ 方法里创建了一个 C 数组,然后在 __init__ 中填充数据(记得用 __dealloc__ 来正确清理)。这样做会失去一些 numpy 数组的功能,但你仍然可以像使用 C 数组那样使用它。
你也可以看看这个旧邮件中关于 cython 的讨论:
http://codespeak.net/pipermail/cython-dev/2009-April/005214.html
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)