Reputation: 8090
I'm trying to convert some of my Python code to Cython and experience some issues when I try to define a function as cdef
.
Most of the issues boil down to masking not working as in Python. I wonder if this is a limitation of cdef
(works fine if I leave it as def
) or whether there's something I could do.
For instance this method
cdef func(double[:,:,:,:] arg1):
mask = arg1 > 0
...
already fails with a compile error:
Error compiling Cython file:
------------------------------------------------------------ ...
func (double[:,:,:,:] arg1):
mask = arg1 > 0
^
------------------------------------------------------------
cythonfile.pyx:43:20: Invalid types for '>' (double[:, :, :, :], long)
Upvotes: 2
Views: 548
Reputation: 152775
The double[:,:,:,:]
notation specifies that the argument will be "interpreted" as Typed Memoryview. These support a lot of operations but the vectorized comparisons are not supported.
However it's quite easy to interpret a memory-view as NumPy array inside the function:
import numpy as np
cdef func(double[:,:,:,:] arg1):
arg1arr = np.asarray(arg1)
mask = arg1arr > 0.
That doesn't even need a copy so it's basically "free" to do the np.asarray
on the memory-view. That allows to combine the advantages of the memory-views with the vectorized operations that are possible on NumPy arrays.
However for vectorized operations you don't need Cython, you could do all the vectorized operations in a pure python function and only use Cython for the heavy-lifting that isn't possible with "normal NumPy" functions.
Upvotes: 1
Reputation: 36815
The docs consistently use np.ndarray[...]
in function definitions so I would change your function signature to
cdef func(np.ndarray[np.float_t, ndim=4] arg1):
Also, you are comparing a float
array with an long integer
constant. Change it to
mask = arg1 > 0.
to compare float
with float
.
Upvotes: 1