我最近从Matlab
to Python
。在转换我的一个冗长代码时,我惊讶地发现Python
非常慢。我分析并追踪了一个函数占用时间的问题。该函数是从我的代码中的各个位置调用的(作为递归调用的其他函数的一部分)。探查器建议300两个地方都调用了这个函数Matlab
and 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
RESULTS
比较结果似乎Matlab
在“”之后大约快 42 倍clear all
" 被调用,如果脚本多次运行而不调用 ",那么速度会快 100 倍clear all
“。这至少是一个数量级,如果不是快两个数量级的话。这对我来说是一个非常令人惊讶的结果。我原以为结果会是相反的。
有人可以解释一下吗?
有人可以建议一种更快的方法来执行此操作吗?
边注
我也尝试过使用numpy.sqrt
这使得性能更差,因此我正在使用math.sqrt
in Python
.
EDIT
The for
调用函数的循环纯粹是虚构的。他们只是为了“simulate" 300调用该函数。正如我之前所描述的,内核函数(kernel_2D
in Matlab
and kex1
in Python
)是从程序中的各个不同位置调用的。为了让问题变得更短,我“simulate" the 300调用使用for
环形。这for
由于核矩阵的结构,核函数内部的循环是必要且不可避免的。
EDIT 2
这是更大的问题:https://github.com/drfahdsiddiqui/bbfmm2d-python https://github.com/drfahdsiddiqui/bbfmm2d-python