python - Passing and returning numpy arrays to C++ methods via Cython -
there lots of questions using numpy in cython on site, particularly useful 1 being simple wrapping of c code cython.
however, cython/numpy interface api seems have changed bit, in particular ensuring passing of memory-contiguous arrays.
what best way write wrapper function in cython that:
- takes numpy array not contiguous
- calls c++ class method signature
double* data_in, double* data_out
- returns numpy array of
double*
method wrote to?
my try below:
cimport numpy np import numpy np # suggested jorgeca cdef extern "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)
this code compiles not optimal. have suggestions on improving snippet above?
and (2) throws , "np not defined on line x_c = ...
") when calling @ runtime. exact testing code , error message following:
import numpy np import mywrapper mywrapper.run(np.array([[1,2],[3,4]], dtype=np.double)) # nameerror: name 'np' not defined [at mywrapper.pyx":x_c = ...] # fixed!
you've got right. first, optimization shouldn't big deal. ideally, of time spent inside c++ kernel, not in cythnon wrapper code.
there few stylistic changes can make simplify code. (1) reshaping between 1d , 2d arrays not necessary. when know memory layout of data (c-order vs. fortran order, striding, etc), can see array chunk of memory you're going index in c++, numpy's ndim doesn't matter on c++ side -- it's seeing pointer. (2) using cython's address-of operator &
, can pointer start of array in little cleaner way -- no explicit cast necessary -- using &x[0,0]
.
so edited version of original snippet:
cimport numpy np import numpy np cdef extern "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
Comments
Post a Comment