title: No speed gains from Cython
body: <p>I am trying to define a function that contains an inner loop for simulating an integral.</p>
  
  <p>The problem is speed. Evaluating the function once can take up to 30 seconds on my machine. Since my ultimate goal is to minimize this function, some extra speed would be nice.</p>
  
  <p>As such, I have tried to get Cython to work, but I must be making a severe mistake (likely many of them!). Following the Cython documentation, I have tried to type my variables. After doing so, the code is just as slow as pure Python. This seems strange.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>import numpy as np 
  cimport cython
  cimport numpy as np
  import minuit
  
  data = np.genfromtxt('q6data.csv', usecols = np.arange(1, 24, 1), delimiter = ',')  
  
  cdef int ns    = 1000                 # Number of simulation draws
  cdef int K     = 5                    # Number of observed characteristics, including            constant
  cdef int J     = len(data[:,1])       # Number of products, including outside
  cdef double tol   = 0.0001            # Inner GMM loop tolerance
  nu = np.random.normal(0, 1, (6, ns))  # ns random deviates
  
  @cython.boundscheck(False)
  @cython.wraparound(False)
  
  
  def S(np.ndarray[double, ndim=1] delta, double s1, double s2, double s3, double s4,  double s5, double a):
      """Computes the simulated integrals, one for each good.
      Parameters: delta is an array of length J containing mean product specific utility levels
      Returns: Numpy array with length J."""
      cdef np.ndarray[double, ndim=2] mu_ij = np.dot((data[:,2:7]*np.array([s1, s2, s3, s4, s5])), nu[1:K+1,:])
      cdef np.ndarray[double, ndim=2] mu_y  = a * np.log(np.exp(data[:,21].reshape(J,1) +  data[:,22].reshape(J,1)*nu[0,:].reshape(1, ns)) - data[:,7].reshape(J,1))
      cdef np.ndarray[double, ndim=2] V = delta.reshape(J,1) + mu_ij + mu_y
      cdef np.ndarray[double, ndim=2] exp_vi = np.exp(V)
      cdef np.ndarray[double, ndim=2] P_i = (1.0 / np.sum(exp_vi[np.where(data[:,1] == 71)], 0)) * exp_vi[np.where(data[:,1] == 71)] 
      cdef int yrs = 19
      cdef int yr
      for yr in xrange(yrs):
          P_yr = (1.0 / np.sum(exp_vi[np.where(data[:,1]== (yr + 72))], 0)) *   exp_vi[np.where(data[:,1] == (yr + 72))]
          P_i  = np.concatenate((P_i, P_yr)) 
      cdef np.ndarray[double, ndim=1] S = np.zeros(dtype = "d", shape = J)
      cdef int j
      for j in xrange(ns):
          S += P_i[:,j]
      return (1.0 / ns) * S
  
  def d_infty(np.ndarray[double, ndim=1] x, np.ndarray[double, ndim=1] y):
      """Sup norm."""
      return np.max(np.abs(x - y)) 
  
  def T(np.ndarray[double, ndim=1] delta_exp, double s1, double s2, double s3, double s4,  double s5, double a):
      """The contraction operator.  This function takes the parameters and the exponential
      of the starting value of delta and returns the fixed point.""" 
      cdef int iter = 0
      cdef int maxiter = 200
      cdef int i
      for i in xrange(maxiter): 
          delta1_exp = delta_exp * (data[:, 8] / S(np.log(delta_exp), s1, s2, s3, s4, s5, a))                    
          print i
          if d_infty(delta_exp, delta1_exp) &lt; tol:                                       
              break
          delta_exp = delta1_exp
      return np.log(delta1_exp)
  
  
  def Q(double s1, double s2, double s3, double s4, double s5, double a):
      """GMM objective function."""  
      cdef np.ndarray[double, ndim=1] delta0_exp = np.exp(data[:,10])                                                     
      cdef np.ndarray[double, ndim=1] delta1 = T(delta0_exp, s1, s2, s3, s4, s5, a)
      delta1[np.where(data[:,10]==0)] = np.zeros(len(np.where(data[:,10]==0)))            
      cdef np.ndarray[double, ndim=1] xi =  delta1 - (np.dot(data[:,2:7],   np.linalg.lstsq(data[:,2:7], delta1)[0]))   
      cdef np.ndarray[double, ndim=2] g_J = xi.reshape(J,1) * data[:,11:21]
      cdef np.ndarray[double, ndim=1] G_J = (1.0 / J) * np.sum(g_J, 0) 
      return np.sqrt(np.dot(G_J, G_J))
  </code></pre>
  
  <p>I have profiled the code, and it seems to be the function S, the integral simulator, that is killing performance. Anyway, I would have expected at least some speed gains from typing my variables. Since it produced no gains, I am led to believe that I am making some fundamental mistakes.</p>
  
  <p>Does anybody see a glaring error in the Cython code that could lead to this result?</p>
  
  <p>Oh, and since I am very new to programming, there is surely a lot of bad style and things slowing the code down. If you have the time, feel free to set me straight on these points as well.  </p>