2012-01-10 30 views
20

Quiero tener un objeto Cython "cdef" con un miembro NumPy, y ser capaz de utilizar el acceso rápido al búfer. Idealmente, me gustaría hacer algo como:Declaraciones de búfer de Cython para miembros de objeto

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) 

Desafortunadamente, Cython no puede compilar este, con el error Buffer types only allowed as function local variables.

La solución que estoy usando es declarar el buffer de atributos en una nueva variable local, asignado al miembro de objeto:

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 

Esto se vuelve muy molesto si usted quiere tener múltiples métodos de acceso a los mismos datos estructuras - que parece un caso de uso bastante común, ¿no?

¿Existe alguna solución mejor que no requiera volver a declarar los tipos dentro de cada método?

Respuesta

6

La solución que está utilizando actualmente es lo que suelo usar, es decir, hacer una copia local en la función. No es elegante, pero no creo que tengas un gran golpe de rendimiento (o al menos en mi caso, estoy trabajando mucho en el método, por lo que no hace una diferencia discernible). También creé un C-array en el método __cinit__ y luego lo llené con los datos en __init__ (asegúrese de usar __dealloc__ para limpiarlo correctamente). Pierdes algunas de las características de la matriz numpy, pero aún puedes usarla como lo harías con una matriz c.

Es posible que también echa un vistazo a la discusión de este mensaje más antiguo en la lista Cython:

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

+2

actualizados enlace http://www.mail-archive.com/[email protected]/msg05166.html – gg349

+0

¿Esto puede perder rendimiento? – machen

13

Existe la opción de trabajar con rodajas de memoria o matrices 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) 
+0

Cuando utiliza este enfoque memoryviews, puede perder rendimiento? Perfilo esto: stringsource: 368 (__ dealloc__) y stringsource: 341 (__ cinit__). Por cierto, esto también se trata en https://stackoverflow.com/questions/21056696/when-profiling-cython-code-what-is-stringsource – machen

+0

¿Cuál es la solución más elegante sobre este problema de requisito? – machen

Cuestiones relacionadas