问题
I have a class with properties in it (let say the name of the class file is inputvar),
I use it as the input argument for two different functions, which have an exactly the same calculation, but a little bit different code, which I'll explain later.
For the first function (let say the name is myfun1), I wrote the input argument like this:
f = myfun1 (inputvar)
So every time I want to use variables from the class inside the function, I'll have to call inputvar.var1, inputvar.var2, and etc.
For the second function (myfun2), I wrote each variables from the class in the input argument, so it looks like this:
f = myfun2 (inputvar.var1, inputvar.var2, ... etc )
Inside the function, I just have to use var1, var2, and etc, without having to include the name of the class.
After running both functions, I found that myfun2 runs a lot faster than myfun1, about 60% (I used tic-toc).
Can someone explain to me exactly why is that ?
回答1:
with the reference:
MATLAB uses a system commonly called "copy-on-write" to avoid making a copy of the input argument inside the function workspace until or unless you modify the input argument. If you do not modify the input argument, MATLAB will avoid making a copy. For instance, in this code:
function y = functionOfLargeMatrix(x) y = x(1); MATLAB will not make a copy of the input in the workspace of functionOfLargeMatrix, as x is not being changed in that function. If on the other hand, you called this function:
function y = functionOfLargeMatrix2(x) x(2) = 2; y = x(1); then x is being modified inside the workspace of functionOfLargeMatrix2, and so a copy must be made.
According to the statement above, when you directly pass a class object and you change any member of this object, a whole copy operation for the class is applied.
On the other side, with giving the class members as separate arguments, copy operation is applied only for the related members modified in the function, resulting in a faster execution.
回答2:
I found that accessing properties is very slow in Matlab. I have not found a way around it, but some basic ideas are found here: http://blogs.mathworks.com/loren/2012/03/26/considering-performance-in-object-oriented-matlab-code/
But this article talks only about avoiding horrible, abysmal performance. Even with the simplest properties, performance is mediocre at best.
Take the example class from the Mathworks article. I did small test script:
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
With these results:
Elapsed time is 6.141445 seconds.
Elapsed time is 0.006245 seconds.
Elapsed time is 0.002116 seconds.
Elapsed time is 0.000478 seconds.
As you can see, every property access is slowing down. Try to vectorize (as always) but even the simple for-loop outperforms the vectorized OOP solution for small n. (On my PC, they break even at 1e7)
Essential message: OOP in Matlab is slow! You pay the price for every property access.
To your question: When you call
myfun2 (inputvar.var1, inputvar.var2, ... etc )
the values are copied. Within the function, you are no longer dealing with classes. Access to variables is fast. However, if you pass the whole class, every access to a property is slow. You can circumvent this by caching all properties in local variables and use these.
If you modify the class to inherit from handle everything gets a bit faster, but the difference is negligible.
来源:https://stackoverflow.com/questions/17932396/matlab-function-passing-by-reference