I've created a Cython code to make matrix operations between a dense matrix and a sparse vector,as follows (as I'm learning Cython I'm not sure this is a good code, but it's the best I could come up with so far):
import numpy as np
cimport numpy as np
ctypedef np.float64_t dtype_t
ctypedef np.int32_t dtypei_t
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def cdenseXsparse(np.ndarray[dtype_t, ndim = 2] Y,
np.ndarray[dtype_t, ndim = 1] V,
np.ndarray[dtypei_t, ndim = 1] I,
np.ndarray[dtype_t, ndim = 1] A = None):
"""
Computes A = Y * (V_I)
"""
if Y is None:
raise ValueError("Input cannot be Null")
A = np.zeros(Y.shape[1])
cdef Py_ssize_t i, indice
cdef dtype_t s
for i in range(A.shape[0]):
s = 0
for indice in range(len(I)):
s += Y[I[indice], i] * V[indice]
A[i] = s
return A
It works fine. But when I change the third line from:
ctypedef np.float64_t dtype_t
to:
ctypedef np.float32_t dtype_t
and compile the .pyx file and run again the matrix operations I get the error:
"Buffer dtype mismatch, expected 'dtype_t' but got 'long'"
As an example, when compiling using np.float32_t and running the code:
In [3]: from numpy import random as rd, array, int32, float32
In [4]: y = array(rd.rand(10, 200), dtype = float32)
In [5]: v = array([1, 2, 3], dtype = float32)
In [6]: i = array([0, 1, 2], dtype = int32)
In [7]: from cdenseXsparse import cdenseXsparse
In [8]: r = cdenseXsparse(y, v, i)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-8-319f9c8c8d49> in <module>()
----> 1 r = cdenseXsparse(y, v, i)
/home/will/workspace/s3_RecSys/SVD/cdenseXsparse.so in cdenseXsparse.cdenseXsparse (cdenseXsparse.c:1484)()
ValueError: Buffer dtype mismatch, expected 'dtype_t' but got 'double'
Is there a different way to use float32 in Cython? Using float64 and float32 shouldn't work the same way?
For what I've researched so far it should work the same, but it didn't in that code.
Thanks in advance!
The default behaviour of np.zeros is to create a float64 data, if you want to force the datatype to be float32 you should specify it. You should also put all cdefs in the beginning of the function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With