Объявления буфера Cython для членов объекта - PullRequest
21 голосов
/ 10 января 2012

Я хочу иметь объект "cdef" на Cython с элементом 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 не может скомпилировать это с ошибкой 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 ]

13 голосов
/ 07 сентября 2013

Есть опция для работы с кусочками памяти или массивами 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)
6 голосов
/ 10 января 2012

Я использую решение, которое вы используете в данный момент, то есть сделайте локальное копирование в функции.Это не элегантно, но я не думаю, что вы сильно пострадали от производительности (или, по крайней мере, в моем случае, я много работаю над этим методом, так что это не делает заметной разницы).Я также создал C-массив в методе __cinit__, а затем заполнил его данными в __init__ (убедитесь, что вы используете __dealloc__ для правильной очистки).Вы теряете некоторые функции массива numpy, но вы все равно можете использовать его, как если бы вы использовали c-массив.

Вы также можете ознакомиться с обсуждением в этом старом письме в списке Cython:

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

...