2012-02-26 19 views
11

he el siguiente código que se va a convertir propperly a Cython:Numpy-> Cython conversión: Error de compilación: No se puede convertir 'npy_intp *' al objeto de Python

from numpy import * 

## returns winning players or [] if undecided. 
def score(board): 
    scores = [] 
    checked = zeros(board.shape) 
    for i in xrange(len(board)): 
     for j in xrange(len(board)): 
      if checked[i,j] == 0 and board[i,j] !=0: 
       ... do stuf 

mi intento de conversión a Cython:

import numpy as np 
cimport numpy as np 

@cython.boundscheck(False) 
@cython.wraparound(False) 
@cython.nonecheck(False) 

## returns winning players or [] if undecided. 
def score(np.ndarray[int, ndim=2] board): 
    scores = [] 
    cdef np.ndarray[int, ndim = 2 ] checked 
    checked = np.zeros(board.shape) 
    for i in xrange(len(board)): 
     for j in xrange(len(board)): 
      if checked[i,j] == 0 and board[i,j] !=0: 
       ... do stuf 

Pero cuando compilo me sale:

$ python setup.py build_ext --inplace 
running build_ext 
cythoning newgox.pyx to newgox.c 


## returns winning players or [] if undecided. 
def score(np.ndarray[int, ndim=2] board): 
    scores = [] 
    cdef np.ndarray[int, ndim = 2 ] checked 
    checked = np.zeros(board.shape) 
        ^
------------------------------------------------------------ 

newgox.pyx:58:28: Cannot convert 'npy_intp *' to Python object 
building 'newgox' extension 

Además, no estoy seguro de que esta es la forma correcta de trabajar con lis TS en Cython:

scores = [] 
if some_stuff_is_true: 
    scores.append(some_integer) 

EDIT:

Gracias, el código ahora compila pero cuando lo ejecuto me sale el error:

File "newgox.pyx", line 63, in newgox.score (newgox.c:1710) 
    def score(np.ndarray[np.int, ndim=2] board): 
ValueError: Buffer dtype mismatch, expected 'int object' but got 'long' 

Até estas dos opciones:

ctypedef np.int_t DTYPE_t 
DTYPE = np.int 

y continúe a:

board = zeros((5,5), dtype = DTYPE) 
def score(np.ndarray[DTYPE, ndim=2] board): 

o simplemente en ambas declaraciones:

... np.int ... 

Esto se traduce en el mismo error, pero con la firma:

ValueError: Buffer dtype mismatch, expected 'int' but got 'long' 

Gracias bellamyj, pero su código sugerido no se compilará,

$ python setup.py build_ext --inplace 
running build_ext 
cythoning newgox.pyx to newgox.c 
building 'newgox' extension 
gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -arch i386 -arch x86_64 -g -O2 -DNDEBUG -g -O3 -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c newgox.c -o build/temp.macosx-10.6-intel-2.7/newgox.o 

newgox.c:238:31: error: numpy/arrayobject.h: No such file or directory 
newgox.c:239:31: error: numpy/ufuncobject.h: No such file or directory 
newgox.c:356: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__pyx_t_5numpy_int8_t’ 
newgox.c:365: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__pyx_t_5numpy_int16_t’ 
newgox.c:374: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__pyx_t_5numpy_int32_t’ 

Y continúa t o enumerar todos los demás tipos también.

es, entonces, me dice esto:

newgox.c:978: error: expected ‘)’ before ‘*’ token 
newgox.c:979: error: expected ‘)’ before ‘*’ token 
newgox.c:980: error: expected ‘)’ before ‘*’ token 
newgox.c:983: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’ 
newgox.c:984: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’ 
newgox.c:985: error: expected ‘)’ before ‘*’ token 
newgox.c:987: error: ‘__pyx_t_5numpy_int32_t’ undeclared here (not in a function) 
newgox.c: In function ‘__pyx_pf_6newgox_7score’: 
newgox.c:1638: error: ‘PyArrayObject’ undeclared (first use in this function) 
newgox.c:1638: error: (Each undeclared identifier is reported only once 
newgox.c:1638: error: for each function it appears in.) 
newgox.c:1638: error: ‘__pyx_v_checked’ undeclared (first use in this function) 
newgox.c:1659: error: ‘__pyx_t_5’ undeclared (first use in this function) 
newgox.c:1721: error: expected expression before ‘)’ token 
newgox.c:1723: error: expected expression before ‘)’ token 
newgox.c:1747: error: expected expression before ‘)’ token 
newgox.c:1766: error: expected expression before ‘)’ token 
newgox.c:1813: error: expected expression before ‘)’ token 
newgox.c:1846: error: expected expression before ‘)’ token 
newgox.c:1846: error: too many arguments to function ‘__pyx_f_6newgox_check_life’ 
newgox.c:2009: error: expected expression before ‘)’ token 
newgox.c:2009: warning: assignment makes pointer from integer without a cast 
newgox.c:2012: error: expected expression before ‘)’ token 
newgox.c:2032: error: expected expression before ‘)’ token 
newgox.c: At top level: 
newgox.c:2088: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’ 
newgox.c: In function ‘__pyx_f_6newgox_check_life’: 
newgox.c:2124: error: ‘__pyx_v_board’ undeclared (first use in this function) 
newgox.c:2160: error: ‘PyArrayObject’ undeclared (first use in this function) 
newgox.c:2160: error: expected expression before ‘)’ token 
newgox.c:2160: error: too many arguments to function ‘__pyx_f_6newgox_liberty’ 
newgox.c:2420: error: too many arguments to function ‘__pyx_f_6newgox_check_life’ 
newgox.c: At top level: 
newgox.c:2583: error: expected declaration specifiers or ‘...’ before ‘PyArrayObject’ 
newgox.c: In function ‘__pyx_f_6newgox_liberty’: 
newgox.c:2610: error: ‘__pyx_v_board’ undeclared (first use in this function) 
newgox.c: At top level: 
newgox.c:2859: error: expected ‘)’ before ‘*’ token 
newgox.c: In function ‘__pyx_pf_5numpy_7ndarray___getbuffer__’: 
newgox.c:2999: error: ‘PyArray_Descr’ undeclared (first use in this function) 
newgox.c:2999: error: ‘__pyx_v_descr’ undeclared (first use in this function) 
newgox.c:3062: error: ‘PyArrayObject’ undeclared (first use in this function) 
newgox.c:3062: error: expected expression before ‘)’ token 
newgox.c:3071: error: ‘npy_intp’ undeclared (first use in this function) 
newgox.c:3114: error: expected expression before ‘)’ token 
newgox.c:3114: error: ‘NPY_C_CONTIGUOUS’ undeclared (first use in this function) 
newgox.c:3154: error: expected expression before ‘)’ token 
newgox.c:3154: error: ‘NPY_F_CONTIGUOUS’ undeclared (first use in this function) 
newgox.c:3184: error: expected expression before ‘)’ token 
newgox.c:3184: warning: assignment makes pointer from integer without a cast 
newgox.c:3240: error: expected expression before ‘)’ token 
newgox.c:3240: error: subscripted value is neither array nor pointer 
newgox.c:3249: error: expected expression before ‘)’ token 
newgox.c:3249: error: subscripted value is neither array nor pointer 
newgox.c:3262: error: expected expression before ‘)’ token 
newgox.c:3271: error: expected expression before ‘)’ token 
newgox.c:3291: error: expected expression before ‘)’ token 

y algunos más.

aviso que dice:

newgox.c:2160: error: too many arguments to function ‘__pyx_f_6newgox_liberty’ 
newgox.c:2420: error: too many arguments to function ‘__pyx_f_6newgox_check_life’ 

Pero mi llamada de puntuación/1 a check_life es:

life, newly_checked = check_life(i,j,board,[]) 

Y se recibe de esta manera:

# helper functions of score/1 
cdef check_life(int i, int j, np.ndarray[int, ndim=2] board, checked): 
    ... 
    return life, checked 

Por último, lo tipo de tipo de datos es el "i4" que utiliza?

Respuesta

14

No creo que el desempaquetado de tuplas funcione en Cython como lo hace en Python. Debe especificar el tamaño de checked usando (board.shape[0], board.shape[1]).

También necesita especificar el tipo de datos de checked. De forma predeterminada, np.zeros devuelve float64. Debe cambiarlo a int32 para que sea compatible con el tipo declarado.

Aquí hay una versión modificada que debe ejecutarse.

def score(np.ndarray[int, ndim=2] board): 

    cdef np.ndarray[np.int32_t, ndim = 2] checked 
    checked = np.zeros((board.shape[0], board.shape[1]), dtype='i4') 

    for i in xrange(len(board)): 
     for j in xrange(len(board)): 
      if checked[i,j] == 0 and board[i,j] !=0: 
       ... do stuff 

Para responder a la segunda parte de su pregunta - sí se puede añadir a las listas dentro de las funciones Cython. Sin embargo, según tengo entendido, esto implica llamadas a función de Python, por lo que no será más rápido que las mismas operaciones dentro de Python.

Actualización 1:

creo que esos errores se deben a que el compilador no puede encontrar los archivos de cabecera NumPy. Actualice su setup.py para incluir la ruta a esos archivos. La ruta debe salir por la función np.get_include().

import numpy as np 
from distutils.core import setup 
from distutils.extension import Extension 
from Cython.Distutils import build_ext 

setup(
     cmdclass={'build_ext': build_ext}, 
     ext_modules = [ 
       Extension("new_gox", 
         ["new_gox.pyx"], 
         include_dirs=[np.get_include()]) 
        ] 
    ) 

El dtype i4 es un entero de 32 bits. Es equivalente a np.int32.

No estoy seguro de qué está pasando con los errores de 'demasiados argumentos'. Si llama a esa función desde Python, debe declararse como def o cpdef. Las funciones declaradas con cdef solo se pueden llamar desde Cython. Esto se describe here en los documentos de Cython.

1

np.intp es igual a (void *)

definir su tipo de la siguiente manera:

ctypedef np.npy_intp SIZE_t    # Type for indices and counters 

fuente:

NPY_INTP == The enumeration value for a signed integer type which is the same size as a (void *) pointer. This is the type used by all arrays of indices.

Así por ejemplo, en Cython ...

Struct en el archivo de cabecera file.h:

struct Cudamat_Struct1 { 
    float * dataHost; 
    float * dataDevice; 
    int onDevice; 
    int onHost; 
    (void *) shape; 
    int size; 
    int isTrans; // 0 or 1 
    int ownsData; 

}; 

En archivo file.pxd Cython:

cdef extern from "file.h": 
    cdef cppclass c_Cudamat_Struct "Cudamat_Struct": 
     float *dataHost 
     float *dataDevice 
     bint onDevice 
     bint onHost 
     SIZE_t * shape 
     int size 
     bint isTrans 
     bint ownsData 

Finalmente, en función de Cython:

cdef pycublas_thrust_2d(): 
    cdef c_Cudamat_Struct1* mat = new c_Cudamat_Struct1() 

    cdef int N = 10 

    cdef np.ndarray[ndim=2, dtype=F32t] arrHost = np.ones((1,10),dtype=F32) 

    cdef int size = 10 

    cdef F32t[:,:] arrHost_ = arrHost 

    cdef F32t * arrHostPtr = &arrHost[0,0] 

    mat.dataHost = arrHostPtr 
    mat.shape = arrHost.shape 
    mat.size = size 
Cuestiones relacionadas