Speed-up cython code
<p>I have code that is working in python and want to use cython to speed up the calculation. The function that I've copied is in a .pyx file and gets called from my python code. V, C, train, I_k are 2-d numpy arrays and lambda_u, user, hidden are ints. 
I don't have any experience in using C or cython. What is an efficient 
way to make this code faster.
Using <code>cython -a</code> for compiling shows me that the code is flawed but how can I improve it. Using <code>for i in prange (user_size, nogil=True):</code>
results in <code>Constructing Python slice object not allowed without gil</code>.</p>

<p>How has the code to be modified to harvest the power of cython?</p>

<pre><code> @cython.boundscheck(False)
 @cython.wraparound(False)
 def u_update(V, C, train, I_k, lambda_u, user, hidden):
    cdef int user_size = user
    cdef int hidden_dim = hidden
    cdef np.ndarray U = np.empty((hidden_dim,user_size), float)
    cdef int m = C.shape[1]

    for i in range(user_size):
        C_i = np.zeros((m, m), dtype=float)
        for j in range(m):
            C_i[j,j]=C[i,j]

        U[:,i] = np.dot(np.linalg.inv(np.dot(V, np.dot(C_i,V.T)) + lambda_u*I_k), np.dot(V, np.dot(C_i,train[i,:].T)))

    return U
</code></pre>

<p>The first thing that comes to mind is you haven't typed the function arguments and specified the data type and number of dimensions like so :</p>

<pre><code>def u_update(np.ndarray[np.float64, ndim=2]V, np.ndarray[np.float64, ndim=2]\
C, np.ndarray[np.float64, ndim=2] train, np.ndarray[np.float64, ndim=2] \
I_k, int lambda_u, int user, int hidden) :
</code></pre>

<p>This will greatly speed up indexing with 2 indices like you do in the inner loop.</p>

<p>It's best to do this to the array <code>U</code> as well, although you are using slicing:</p>

<pre><code>cdef np.ndarray[np.float64, ndim=2] U = np.empty((hidden_dim,user_size), np.float64)
</code></pre>

<p>Next, you are redefining <code>C_i</code>, a large 2-D array every iteration of the outer loop. Also, you have not supplied any type information for it, which is a must if Cython is to offer any speedup. To fix this :</p>

<pre><code>cdef np.ndarray[np.float64, ndim=2] C_i = np.zeros((m, m), dtype=np.float64)
    for i in range(user_size):
        C_i.fill(0)
</code></pre>

<p>Here, we have defined it once (with type information), and reused the memory by filling with zeros instead of calling <code>np.zeros()</code> to make a new array every time.</p>

<p>Also, you might want to turn off bounds checking only <em>after</em> you have finished debugging.</p>

<p>If you need speedups in the <code>U[:,i]=...</code> step, you could consider writing another function with Cython to perform those operations using loops.</p>

<p>Do read this <a href="http://cython.readthedocs.io/en/latest/src/userguide/numpy_tutorial.html" rel="nofollow">tutorial</a> which should give you an idea of what to do when working with Numpy arrays in Cython and what not to do as well, and also to appreciate how much of a speedup you can get with these simple changes.</p>

python numpy cython