Desempenho: Matlab vs Python

Eu mudei recentemente deMatlab paraPython. Ao converter um dos meus códigos longos, fiquei surpreso ao descobrirPython sendo muito lento. Eu criei um perfil e traçou o problema com uma função que monitora o tempo. Essa função está sendo chamada de vários lugares no meu código (fazendo parte de outras funções que são chamadas recursivamente). O Profiler sugere que300 chamadas são feitas para essa função em ambosMatlab ePython.

Em resumo, os seguintes códigos resumem o problema em questão:

MATLAB

A classe que contém a função:

classdef ExampleKernel1 < 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

e o script para chamar test.m:

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

Dá a saída

clear all
>> test
Elapsed time is 0.022426 seconds.
>> test
Elapsed time is 0.009852 seconds.

PYTHON 3.4

Classe que contém a função CustomKernels.py:

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

e o script para chamar test.py:

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))

Dá a saída

%run test.py
 0.940515 secs
%run test.py
 0.884418 secs
%run test.py
 0.940239 secs

RESULTADOS

Comparando os resultados, pareceMatlab é cerca de 42 vezes mais rápido depois de um "clear all"é chamado e 100 vezes mais rápido se o script for executado várias vezes sem chamar"clear all". Isso é pelo menos uma ordem de magnitude, senão duas ordens de magnitude mais rápidas. Esse é um resultado muito surpreendente para mim. Eu esperava que o resultado fosse o contrário.

Alguém por favor pode lançar alguma luz sobre isso?

Alguém pode sugerir uma maneira mais rápida de fazer isso?

NOTA

Eu também tentei usarnumpy.sqrt o que piora o desempenho, por isso estou usandomath.sqrt noPython.

EDITAR

ofor os loops para chamar as funções são puramente fictícios. Eles estão lá apenas para "simular" 300 chama para a função. Como descrevi anteriormente, o kernel funciona (kernel_2D noMatlab ekex1 noPython) são chamados de vários lugares diferentes do programa. Para diminuir o problema, eu "simular" a300 chamadas usando ofor ciclo. ofor loops dentro das funções do kernel são essenciais e inevitáveis devido à estrutura da matriz do kernel.

EDIT 2

Aqui está o problema maior:https://github.com/drfahdsiddiqui/bbfmm2d-python

questionAnswers(5)

yourAnswerToTheQuestion