Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在MATLAB中使用匿名函数的性能较慢。。。其他人注意到了吗?_Matlab_Performance_Anonymous Function - Fatal编程技术网

在MATLAB中使用匿名函数的性能较慢。。。其他人注意到了吗?

在MATLAB中使用匿名函数的性能较慢。。。其他人注意到了吗?,matlab,performance,anonymous-function,Matlab,Performance,Anonymous Function,为了重构我的MATLAB代码,我想我应该将函数作为参数传递(MATLAB称之为匿名函数),灵感来自函数编程 然而,性能似乎受到了相当严重的影响。在下面的例子中,我比较了不同的方法。(代码段包装在函数中,以便能够使用子函数) 我得到的结果是直接0秒,使用子函数几乎0秒,使用匿名函数5秒。我在OSX10.6上运行Matlab7.7(R2007b),在C2D1.8GHz上运行 任何人都可以运行代码,看看他们得到了什么?我对Windows上的性能特别感兴趣 function [] = speedtest

为了重构我的MATLAB代码,我想我应该将函数作为参数传递(MATLAB称之为匿名函数),灵感来自函数编程

然而,性能似乎受到了相当严重的影响。在下面的例子中,我比较了不同的方法。(代码段包装在函数中,以便能够使用子函数)

我得到的结果是直接0秒,使用子函数几乎0秒,使用匿名函数5秒。我在OSX10.6上运行Matlab7.7(R2007b),在C2D1.8GHz上运行

任何人都可以运行代码,看看他们得到了什么?我对Windows上的性能特别感兴趣

function [] = speedtest()


clear all; close all;

function y = foo(x)
    y = zeros(1,length(x));
    for j=1:N
        y(j) = x(j)^2;
    end
end

x = linspace(-100,100,100000);
N = length(x);


%% direct
t = cputime;

y = zeros(1,N);
for i=1:N
    y(i) = x(i)^2;
end

r1 = cputime - t;

%% using subfunction
t = cputime;
y = foo(x);
r2 = cputime - t;

%% using anon function
fn = @(x) x^2;

t = cputime;

y = zeros(1,N);
for i=1:N
    y(i) = fn(x(i));
end

r3 = cputime-t;

[r1 r2 r3]

end
>> speedtest direct: 0 nested: 0.0469 nested_handle: 0.0781 subfunction: 0.0313 subfunction_handle: 0.0313 anonymous: 1.2344
来自Windows机器的结果,Matlab 2009a

>> test

ans =

     0    0.0156    1.1094

我可以证实你的发现。speedtest函数在我的计算机上返回以下内容

>> speedtest()
ans =
         0    0.0313    1.3906
作为旁注,函数cputime不是测量计算时间的最佳方法。改用tic和toc功能。 这些函数提供了更高的时间分辨率,使用它们我可以获得以下结果

>> speedtest()
ans =
         0.0062    0.0162    1.3495

您正在使用嵌套函数作弊。:)匿名函数在一个循环中被调用,因此您要衡量调用它100000次的成本。嵌套函数只调用一次,因此其函数调用开销可以忽略不计。要比较调用匿名函数和命名函数的成本,应该让嵌套函数执行与匿名函数相同的工作,然后也从循环内部调用它

我做到了,但仍然得到了类似的结果。匿名函数的速度大约慢20倍

但是,您仍然可以对非匿名函数使用函数句柄,这与匿名函数的性能影响不同。这适用于嵌套函数(与原始测试中的foo一样)或非嵌套子函数(不充当闭包,开销可能更小)

我在Windows的R2009b上得到这个

function [] = speedtest()


clear all; close all;

function y = foo(x)
    y = zeros(1,length(x));
    for j=1:N
        y(j) = x(j)^2;
    end
end

x = linspace(-100,100,100000);
N = length(x);


%% direct
t = cputime;

y = zeros(1,N);
for i=1:N
    y(i) = x(i)^2;
end

r1 = cputime - t;

%% using subfunction
t = cputime;
y = foo(x);
r2 = cputime - t;

%% using anon function
fn = @(x) x^2;

t = cputime;

y = zeros(1,N);
for i=1:N
    y(i) = fn(x(i));
end

r3 = cputime-t;

[r1 r2 r3]

end
>> speedtest direct: 0 nested: 0.0469 nested_handle: 0.0781 subfunction: 0.0313 subfunction_handle: 0.0313 anonymous: 1.2344 >>速度测试 直接:0 嵌套:0.0469 嵌套_句柄:0.0781 子功能:0.0313 子功能_句柄:0.0313 匿名电话:1.2344
另一种方法是构造代码,使其“矢量化”并在数组上运行,减少函数调用的数量,而函数调用的成本并不重要。这将是更为惯用的Matlab:典型的性能建议是忽略函数调用和循环的成本,因为无论如何,你应该在较大的参数上进行更少的调用。

我和Gary面临同样的问题,只是认为最好在更新版本的Matlab(2014a)(Mac)上检查Andrew的答案。结果首先是:

direct: 0.0722
anonymous: 0.3916
subfunction: 0.2277
我使用的代码是:

function []=SpeedTest()

fanon = @(x,y) x*x+y*y;

iter=1000000;
x=1:iter;
y=1:iter;
var1=nan(size(x));
var2=nan(size(x));
var3=nan(size(x));
timefor=struct('direct',nan,'anonymous',nan','subfunction',nan);

tic;
for i=1:iter
    var1(i)=x(i)*x(i)+y(i)*y(i);
end
timefor.direct=toc;

tic;
for i=1:iter
    var2(i)=fanon(x(i),y(i));
end
timefor.anonymous=toc;

tic;
for i=1:iter
    var3(i)=fsub(x(i),y(i));
end
timefor.subfunction=toc;

display(timefor);
end

function [z]=fsub(x,y)
z=x*x+y*y;
end

你的问题到底是什么?我想知道你为什么要做这么复杂的计算。。。您可以使用向量操作来代替for循环的需要。例如,
y=x.^2
将对
x
的每个元素进行平方运算,并将结果向量保存在
y
中。仅供参考:OOP方法调度性能的类似问题:作为midtiby评论的后续内容,对MATLAB代码计时的最佳方法是使用文件交换中的timeit。它处理诸如首次运行启动成本之类的问题,并计算至少10次运行的稳态平均运行时间。它比普通的tic/toc对可靠得多。小错误:在你的代码中,你所谓的“子函数”实际上是你的嵌套函数,而你所谓的“局部函数”实际上是子函数;“子功能”是现在。是的,你是对的-我在作弊。但不是故意的;-)我现在已经习惯于矢量化我的代码,例如,避免for循环,而是做一些类似于(A@Grav:非惯用的不是匿名性,而是一小部分工作。我的意思是,导致函数调用次数大大减少的向量化代码(每个函数调用都适用于较大的输入数组)是惯用的Matlab。听起来你的思路是对的。如果方便的话,可以使用Anon;只要将它们设置为vec像“@(x)x.^2”这样的torized,那么性能冲击就不那么重要了。