MATLAB函数通过引用传递

时间:2013-07-29 19:18:23

标签: matlab memory memory-management pass-by-reference

我有一个包含属性的类(假设类文件的名称是inputvar),

我将它用作两个不同函数的输入参数,这两个函数具有完全相同的计算,但稍微有点不同的代码,我将在后面解释。

对于第一个函数(假设名称是myfun1),我写了这样的输入参数:

f = myfun1 (inputvar)

因此,每次我想在函数内部使用类中的变量时,我都必须调用inputvar.var1inputvar.var2等。

对于第二个函数(myfun2),我在输入参数中从类中编写了每个变量,所以它看起来像这样:

f = myfun2 (inputvar.var1, inputvar.var2, ... etc )

在函数内部,我只需使用var1var2等,而不必包含类的名称。

运行这两个函数后,我发现myfun2的运行速度比myfun1快很多,约为60%(我使用了tic-toc)。

有人可以向我解释为什么会这样吗?

2 个答案:

答案 0 :(得分:3)

使用reference

  

MATLAB使用通常称为“写时复制”的系统来避免制作   函数工作区内的输入参数的副本,直到或   除非您修改输入参数。如果您不修改输入   参数,MATLAB将避免复制。例如,在此代码中:

     

function y = functionOfLargeMatrix(x)y = x(1); MATLAB不会制作一个   functionOfLargeMatrix工作空间中输入的副本,如x所示   没有改变那个功能。如果另一方面,你打电话   这个功能:

     

函数y = functionOfLargeMatrix2(x)x(2)= 2; y = x(1);   然后在functionOfLargeMatrix2的工作区内修改x,因此必须复制。

根据上面的语句,当您直接传递类对象并更改此对象的任何成员时,将应用该类的整个复制操作。

另一方面,通过将类成员作为单独的参数,复制操作仅适用于在函数中修改的相关成员,从而加快执行速度。

答案 1 :(得分:3)

我发现在Matlab中访问属性非常慢。我没有找到解决方法,但是在这里可以找到一些基本的想法:http://blogs.mathworks.com/loren/2012/03/26/considering-performance-in-object-oriented-matlab-code/

但是这篇文章只讨论避免可怕的,糟糕的表现。即使具有最简单的属性,性能也是最平庸的。

从Mathworks文章中获取示例类。我做了小测试脚本:

clear all
clc
n = 1e5;
%% OOP way - abysimal
result = zeros(1, n);
tic
for i = 1:n
    cyl = SimpleCylinder();
    cyl.R = i;
    cyl.Height = 10;
    result(i) = cyl.volume();
end
toc
%% OOP Vectorized - fair
clear result
tic
cyl = SimpleCylinder();
cyl.R = 1:n;
cyl.Height = 10;
result = cyl.volume();
toc
%% for loop without objects - good
result = zeros(1, n);
tic
for i = 1:n
    result(i) = pi .* i.^2 .* 10;
end
toc
%% Vectorized without objects - excellent
clear result
tic
R = 1:n;
result = pi .* R.^2 .* 10;
toc

有了这些结果:

Elapsed time is 6.141445 seconds.
Elapsed time is 0.006245 seconds.
Elapsed time is 0.002116 seconds.
Elapsed time is 0.000478 seconds.

正如您所看到的,每个属性访问都在减慢。尝试矢量化(一如既往),但即使是简单的for-loop也优于小n的矢量化OOP解决方案。 (在我的电脑上,他们在1e7时收支平衡)

基本信息:Matlab中的OOP很慢!您支付每次入住物业的价格。


提出问题:致电时

myfun2 (inputvar.var1, inputvar.var2, ... etc )

复制值。在函数中,您不再处理类。访问变量很快。但是,如果您传递整个类,则对属性的每次访问都很慢。您可以通过缓存局部变量中的所有属性来避免这种情况并使用它们。


如果您修改要从句柄继承的类,一切都会快一点,但差别可以忽略不计。