tutorial - python iterate numpy array
Pasar y devolver matrices numpy a métodos C++ a través de Cython (1)
Básicamente lo has hecho bien. En primer lugar, espero que la optimización no sea un gran problema. Idealmente, la mayor parte del tiempo se pasa dentro de su núcleo de C ++, no en el código de envoltorio de cythnon.
Hay algunos cambios estilísticos que puedes hacer que simplificarán tu código. (1) No es necesario remodelar entre arreglos 1D y 2D. Cuando conoce el diseño de memoria de sus datos (orden C vs. orden fortran, zancada, etc.), puede ver la matriz como solo una parte de la memoria que se va a indexar en C ++, por lo que el ndim de numpy no lo hace No importa en el lado de C ++, solo está viendo ese puntero. (2) Utilizando el operador de la dirección de cython &
, puede llevar el puntero al inicio de la matriz de una forma un poco más limpia, sin necesidad de conversión explícita, utilizando &X[0,0]
.
Así que esta es mi versión editada de su fragmento original:
cimport numpy as np
import numpy as np
cdef extern from "myclass.h":
cdef cppclass MyClass:
MyClass() except +
void run(double* X, int N, int D, double* Y)
def run(np.ndarray[np.double_t, ndim=2] X):
X = np.ascontiguousarray(X)
cdef np.ndarray[np.double_t, ndim=2, mode="c"] Y = np.zeros_like(X)
cdef MyClass myclass
myclass = MyClass()
myclass.run(&X[0,0], X.shape[0], X.shape[1], &Y[0,0])
return Y
Hay muchas preguntas sobre el uso de numpy en cython en este sitio, una particularmente útil es el simple ajuste del código C con cython .
Sin embargo, la interfaz de la interfaz cython / numpy parece haber cambiado un poco , en particular para garantizar el paso de matrices contiguas a la memoria.
¿Cuál es la mejor manera de escribir una función de envoltorio en cython que:
- toma una matriz numpy que es probable pero no necesariamente contigua
- llama a un método de clase C ++ con la firma
double* data_in, double* data_out
- devuelve una matriz numpy del
double*
que escribió el método?
Mi intento está abajo:
cimport numpy as np
import numpy as np # as suggested by jorgeca
cdef extern from "myclass.h":
cdef cppclass MyClass:
MyClass() except +
void run(double* X, int N, int D, double* Y)
def run(np.ndarray[np.double_t, ndim=2] X):
cdef int N, D
N = X.shape[0]
D = X.shape[1]
cdef np.ndarray[np.double_t, ndim=1, mode="c"] X_c
X_c = np.ascontiguousarray(X, dtype=np.double)
cdef np.ndarray[np.double_t, ndim=1, mode="c"] Y_c
Y_c = np.ascontiguousarray(np.zeros((N*D,)), dtype=np.double)
cdef MyClass myclass
myclass = MyClass()
myclass.run(<double*> X_c.data, N, D, <double*> Y_c.data)
return Y_c.reshape(N, 2)
Este código compila pero no es necesariamente óptimo. ¿Tiene alguna sugerencia para mejorar el fragmento de arriba?
y (2) lanzamientos y "np no está definido en la línea X_c = ...
" cuando se llama en tiempo de ejecución.El código de prueba exacto y el mensaje de error son los siguientes:
import numpy as np
import mywrapper
mywrapper.run(np.array([[1,2],[3,4]], dtype=np.double))
# NameError: name ''np'' is not defined [at mywrapper.pyx":X_c = ...]
# fixed!