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