Я получил ~ 5-кратное улучшение скорости по сравнению с сеткой, используя только трансляцию:
авно перешел сMatlab
вPython
, Преобразуя один из моих длинных кодов, я с удивлением обнаружил,Python
быть очень медленным Я профилировал и проследил проблему с одной функцией, тянущей время. Эта функция вызывается из разных мест в моем коде (будучи частью других функций, которые вызываются рекурсивно). Профилировщик предполагает, что300 звонки на эту функцию в обоихMatlab
а такжеPython
.
Вкратце, следующие коды кратко описывают проблему:
MATLAB
Класс, содержащий функцию:
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
и скрипт для вызова 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
Дает вывод
clear all
>> test
Elapsed time is 0.022426 seconds.
>> test
Elapsed time is 0.009852 seconds.
PYTHON 3.4
Класс, содержащий функцию 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
и скрипт для вызова 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))
Дает вывод
%run test.py
0.940515 secs
%run test.py
0.884418 secs
%run test.py
0.940239 secs
РЕЗУЛЬТАТЫ
Сравнивая результаты, кажется,Matlab
примерно в 42 раза быстрее послеclear all
"вызывается, а затем в 100 раз быстрее, если скрипт запускается несколько раз без вызова"clear all
«. По крайней мере, на порядок, если не на два порядка быстрее. Это очень удивительный результат для меня. Я ожидал, что результат будет наоборот.
Может кто-нибудь, пожалуйста, пролить свет на это?
Может кто-нибудь предложить более быстрый способ сделать это?
ПРИМЕЧАНИЕ
Я также пытался использоватьnumpy.sqrt
что ухудшает производительность, поэтому я используюmath.sqrt
вPython
.
РЕДАКТИРОВАТЬ
for
Циклы для вызова функций являются чисто фиктивными. Они там только для того, чтобымоделировать" 300 вызовы функции. Как я описал ранее, функции ядра (kernel_2D
вMatlab
а такжеkex1
вPython
) вызываются из разных мест в программе. Чтобы сделать проблему короче, я "моделировать"300 звонки с использованиемfor
петля.for
Циклы внутри функций ядра являются существенными и неизбежными из-за структуры матрицы ядра.
РЕДАКТИРОВАТЬ 2
Вот большая проблема:https://github.com/drfahdsiddiqui/bbfmm2d-python