对象成员的 Cython 缓冲区声明

发布于 2024-12-26 03:47:40 字数 808 浏览 0 评论 0原文

我想要一个带有 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

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

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

I want to have a Cython "cdef" object with a NumPy member, and be able to use fast buffer access. Ideally, I would do something like:

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)

Unfortunately, Cython can't compile this, with the error Buffer types only allowed as function local variables.

The workaround I'm using is to declare the buffer attributes on a new local variable, assigned to the object member:

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

This becomes really annoying if you want to have multiple methods accessing the same data structures -- which seems like a pretty common use case, no?

Is there a better solution that doesn't require re-declaring the types inside every method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉薄对峙 2025-01-02 03:47:40

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

There is the option to work with memory slices or cython arrays
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)
乖乖哒 2025-01-02 03:47:40

您当前使用的解决方案是我倾向于使用的解决方案,即在函数中制作本地副本。它并不优雅,但我不认为你会受到巨大的性能影响(或者至少就我而言,我在该方法中做了很多工作,所以它不会产生明显的差异)。我还在 __cinit__ 方法中创建了一个 C 数组,然后用 __init__ 中的数据填充它(确保使用 __dealloc__ 正确清理)。您失去了 numpy 数组的一些功能,但您仍然可以像使用 c 数组一样使用它。

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

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

The solution that you are currently using is what I tend to use, i.e. make a local copy in the function. It's not elegant, but I don't think you take a huge performance hit (or at least in my case, I'm doing a lot of work in the method, so it doesn't make a discernible difference). I've also created a C-array in the __cinit__ method and then filled it with the data in __init__ (make sure you use __dealloc__ to clean-up properly). You lose some of the features of the numpy array, but you can still use it as you would a c-array.

You might also check out the discussion in this older email on the cython list:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文