python - 性能:Matlab 与 Python

标签 python matlab performance numpy function-calls

我最近从 Matlab 切换到 Python。在转换我的一个冗长代码时,我惊讶地发现 Python 非常慢。我分析并追踪了一个占用时间的函数的问题。从我的代码中的不同位置调用此函数(作为递归调用的其他函数的一部分)。 Profiler 建议在 MatlabPython 中对该函数进行了 300 次调用。

简而言之,以下代码总结了手头的问题:

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 在调用“clear all”后快了大约 42 倍,如果脚本多次运行而不调用“则快 100 倍” 全部清除”。这至少是一个数量级,如果不是快两个数量级的话。这对我来说是一个非常令人惊讶的结果。我期待结果是相反的。

有人可以解释一下吗?

有人可以建议一种更快的方法来执行此操作吗?

边注

我也尝试过使用 numpy.sqrt 这会使性能更差,因此我在 Python 中使用 math.sqrt

编辑

用于调用函数的 for 循环纯属虚构。它们的存在只是为了“模拟300 次函数调用。如前所述,内核函数(Matlab 中的kernel_2DPython 中的kex1)从各种不同的调用程序中的位置。为了简化问题,我使用 for 循环“模拟”了 300 次调用。由于内核矩阵的结构,内核函数中的 for 循环是必不可少且不可避免的。

编辑 2

这是更大的问题:https://github.com/drfahdsiddiqui/bbfmm2d-python

最佳答案

您想摆脱那些 for 循环。试试这个:

def exampleKernelA(M, x, N, y):
    """Example kernel function A"""
    i, j = np.indices((N, M))
    # Define the custom kernel function here
    kernel[i, j] = np.sqrt((x[i, 0] - y[j, 0]) ** 2 + (x[i, 1] - y[j, 1]) ** 2)
    return kernel

您也可以使用广播来实现,这可能会更快,但在 MATLAB 中不太直观。

关于python - 性能:Matlab 与 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46475162/

相关文章:

Python-机器学习

python - 在不使用 `key` 参数的情况下对自定义类进行排序?

python - `numpy.random.normal` 在不同的系统上生成不同的数字

matlab - 在matlab中将多个字符串合并为一个字符串

java - 是否可以在所有情况下比较两个 .java 文件的方法和字段?

python - 在非间隔段落中查找单词?

matlab - 创建一个零填充的二维数组,其中的元素位于由向量索引的位置

python - python中有matlab中digits()和vpa()函数的对应函数吗?

Java 好奇循环性能

c# - .NET RegExp 引擎搜索性能优化