title: Performance: Matlab vs Python
body: <p>I recently switched from <code>Matlab</code> to <code>Python</code>. While converting one of my lengthy codes, I was surprised to find <code>Python</code> being very slow. I profiled and traced the problem with one function hogging up time. This function is being called from various places in my code (being part of other functions which are recursively called). Profiler suggests that <em>300</em> calls are made to this function in both <code>Matlab</code> and <code>Python</code>.</p>
  
  <p>In short, following codes summarizes the issue at hand:</p>
  
  <p><strong><code>MATLAB</code></strong></p>
  
  <p>The class containing the function:</p>
  
  <pre><code>classdef ExampleKernel1 &lt; handle  
  methods (Static)
      function [kernel] = kernel_2D(M,x,N,y) 
          kernel  = zeros(M,N);
          for i= 1 : M
              for j= 1 : N
                  % Define the custom kernel function here
                  kernel(i , j) = sqrt((x(i , 1) - y(j , 1)) .^ 2 + ...
                                  (x(i , 2) - y(j , 2)) .^2 );             
              end
          end
      end
  end
  end
  </code></pre>
  
  <p>and the script to call test.m:</p>
  
  <pre><code>xVec=[   
  49.7030   78.9590
  42.6730   11.1390
  23.2790   89.6720
  75.6050   25.5890
  81.5820   53.2920
  44.9680    2.7770
  38.7890   78.9050
  39.1570   33.6790
  33.2640   54.7200
  4.8060   44.3660
  49.7030   78.9590
  42.6730   11.1390
  23.2790   89.6720
  75.6050   25.5890
  81.5820   53.2920
  44.9680    2.7770
  38.7890   78.9050
  39.1570   33.6790
  33.2640   54.7200
  4.8060   44.3660
  ];
  N=size(xVec,1);
  kex1=ExampleKernel1;
  tic
  for i=1:300
      K=kex1.kernel_2D(N,xVec,N,xVec);
  end
  toc
  </code></pre>
  
  <p>Gives the output </p>
  
  <pre><code>clear all
  &gt;&gt; test
  Elapsed time is 0.022426 seconds.
  &gt;&gt; test
  Elapsed time is 0.009852 seconds.
  </code></pre>
  
  <p><strong><code>PYTHON 3.4</code></strong></p>
  
  <p>Class containing the function CustomKernels.py:</p>
  
  <pre><code>from numpy import zeros
  from math import sqrt
  class CustomKernels:
  """Class for defining the custom kernel functions"""
      @staticmethod
      def exampleKernelA(M, x, N, y):
          """Example kernel function A"""
          kernel = zeros([M, N])
          for i in range(0, M):
              for j in range(0, N):
                  # Define the custom kernel function here
                  kernel[i, j] = sqrt((x[i, 0] - y[j, 0]) ** 2 + (x[i, 1] - y[j, 1]) ** 2)
          return kernel
  </code></pre>
  
  <p>and the script to call test.py:</p>
  
  <pre><code>import numpy as np
  from CustomKernels import CustomKernels
  from time import perf_counter
  
  xVec = np.array([
      [49.7030,  78.9590],
      [42.6730,  11.1390],
      [23.2790,  89.6720],
      [75.6050,  25.5890],
      [81.5820,  53.2920],
      [44.9680,   2.7770],
      [38.7890,  78.9050],
      [39.1570,  33.6790],
      [33.2640,  54.7200],
      [4.8060 ,  44.3660],
      [49.7030,  78.9590],
      [42.6730,  11.1390],
      [23.2790,  89.6720],
      [75.6050,  25.5890],
      [81.5820,  53.2920],
      [44.9680,   2.7770],
      [38.7890,  78.9050],
      [39.1570,  33.6790],
      [33.2640,  54.7200],
      [4.8060 ,  44.3660]
      ])
  N = xVec.shape[0]
  kex1 = CustomKernels.exampleKernelA
  start=perf_counter()
  for i in range(0,300):
      K = kex1(N, xVec, N, xVec)
  print(' %f secs' %(perf_counter()-start))
  </code></pre>
  
  <p>Gives the output</p>
  
  <pre><code>%run test.py
   0.940515 secs
  %run test.py
   0.884418 secs
  %run test.py
   0.940239 secs
  </code></pre>
  
  <p><strong>RESULTS</strong></p>
  
  <p>Comparing the results it seems <code>Matlab</code> is about 42 times faster after a "<code>clear all</code>" is called and then 100 times faster if script is run multiple times without calling "<code>clear all</code>". That is at least and order of magnitude if not two orders of magnitudes faster. This is a very surprising result for me. I was expecting the result to be the other way around. </p>
  
  <p>Can someone please shed some light on this?</p>
  
  <p>Can someone suggest a faster way to perform this?</p>
  
  <p><strong>SIDE NOTE</strong></p>
  
  <p>I have also tried to use <code>numpy.sqrt</code> which makes the performance worse, therefore I am using <code>math.sqrt</code> in <code>Python</code>.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>The <code>for</code> loops for calling the functions are purely fictitious. They are there just to "<em>simulate</em>" <em>300</em> calls to the function. As I described earlier, the kernel functions (<code>kernel_2D</code> in <code>Matlab</code> and <code>kex1</code> in <code>Python</code>) are called from various different places in the program. To make the problem shorter, I "<em>simulate</em>" the <em>300</em> calls using the <code>for</code> loop. The <code>for</code> loops inside the kernel functions are essential and unavoidable because of the structure of the kernel matrix.</p>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>Here is the larger problem: <a href="https://github.com/drfahdsiddiqui/bbfmm2d-python" rel="nofollow noreferrer">https://github.com/drfahdsiddiqui/bbfmm2d-python</a></p>