MATLAB Answers

Which type of function call provides better performance in MATLAB?

322 views (last 30 days)
I have 7 different types of function call:
1. An inlined function, where the code author replaces the function call with a copy of the body of the function.
2. A function is defined in a separate MATLAB file. The arguments are passed by the calling function (file-pass).
3. A function is defined in a separate MATLAB file. The arguments are provided by referencing global variables; only indices are provided by the calling function (file-global).
4. A nested function. The arguments are passed by the enclosing function (nest-pass).
5. A nested function. The arguments are those shared with the enclosing function; only indices are provided by the enclosing function (nest-share).
6. A sub function. The arguments are passed by the calling function (sub-pass).
7. A sub function. The arguments are provided by referencing global variables; only indices are provided by the calling function (sub-global).
(For more information, please see the following three MATLAB files: testTop.m, testCompute, and testComputeGlobal.m)
I would like to know which function call provides better performance than the others in general.

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 5 Oct 2018
Edited: MathWorks Support Team on 5 Oct 2018
The ordering of performance of each function call from the fastest to the slowest tends to be as follows:
inlined > file-pass = nest-pass = sub-pass > nest-share > sub-global > file-global
(A>B means A is faster than B and A=B means A is as fast as B)
First, using an inlined function is the fastest as it does not incur overhead associated with function call.
Second, when the arguments are passed to the callee function, the calling function sets up the arguments in such a way that the callee function knows where to retrieve them. This setup associated with function call in general incurs performance overhead, and therefore file-pass, nest-pass, and sub-pass are slower than inline.
Third, if the workspace is shared with nested functions and the arguments to a nested function are those shared within the workspace, rather than pass-by-value, then performance of that function call is inhibited. If MATLAB sees a shared variable within the shared workspace, it searches the workspace for the variable. On the other hand, if the arguments are passed by the calling function, then MATLAB does not have to search for them. The time taken for this search explains that type nest-share is slower than file-pass, nest-pass, and sub-pass.
Finally, when a function call involves global variables, performance is even more inhibited. This is because to look for global variables, MATLAB has to expand its search space to the outside of the current workspace. Furthermore, the reason a function call involving global variables appears a lot slower than the others is that MATLAB Accelerator does not optimize such a function call. When MATLAB Accelerator is turned off with the following command,
feature accel off
the difference in performance between inline and file-global becomes less significant.
Please note that the behaviors depend largely on various factors such as operating systems, CPU architectures, MATLAB Interpreter, and what the MATLAB code is doing.
  1 Comment
Walter Roberson
Walter Roberson on 5 Jul 2018
Also note that anonymous function calls are slower than direct function calls, but the difference can vary from almost negligible to being rather substantial in nearly identical code.
(I have some test cases that I put together a couple of years ago, but my system is loaded at the moment so I cannot do timing tests right now.)

Sign in to comment.

More Answers (5)

Robert
Robert on 3 Jul 2018
Helpful stuff, but shouldn't the first alternative read "1. An Inline function. The body of the function is directly written down (inline)."?
  1 Comment
Harsha Phadke
Harsha Phadke on 5 Jul 2018
Thank you for pointing out the error, we've updated the question accordingly.

Sign in to comment.


Hannes Greim
Hannes Greim on 31 Mar 2015
Do the answers change once the code is compiled and run with the MCR?
  1 Comment
Rutuja Shirali
Rutuja Shirali on 7 Jul 2015
The answer still remains the same once the code is compiled and run with MCR. This is because MATLAB Compiler works by running the same MATLAB code (although encrypted) on an installed runtime, and does not change the nature of the code. As such, the compiled MATLAB code will run with similar speed as if running on MATLAB desktop.

Sign in to comment.


Dominique
Dominique on 13 Jun 2020
Hello,
I was reading your comments on using global variables, which are expected to always slow down the running time of any code.
Please check the following code, run on R2019b.
There, you can see that, using a global variable speeds the code by more than a factor of hundred.
Using global variable
Elapsed time is 0.001173 seconds.
Passing variable
Elapsed time is 0.880516 seconds.
Please explain me what's going on here !
Thanks for your help,
==>
n=500000;
global a
a=zeros(100, n);
b=zeros(100, n);
% Using a global variable
disp('Using global variable')
tic
for i=1:100
t=test1;
end
toc
% Doing the same thing passing variable to function
disp('Passing variable')
tic
for i=1:100
t=test2(b(i,:));
end
toc
%Called function when using global variable
function t=test1
global a
t=a(1);
end
%Called function when passing variable
function t=test2(x)
t=x(1);
end
  3 Comments
Steven Lord
Steven Lord on 15 Jun 2020
FYI if you pass a large variable into your function but only read it (don't try to make a copy and don't try to modify it) then the copy on write behavior of MATLAB can avoid making a copy in the function workspace.

Sign in to comment.


Cristian Le
Cristian Le on 26 Jan 2021
With inline currently marked as not recomended, does the annonymous function have the same performance as inline right now?
Let's say I have two calls like in this example:
a = 1;
b = 2;
f_an = @(x) f(x,a,b);
% Substitute the variables as needed
f_in = inline(sprintf('f(x,%d,%d)',a,b),'x');
% Which is better when used as a wrapper function, e.g.
y = ode45(@f_an,..);
% or
y = ode45(@f_in,..);
function y = f(x,a,b)
% Main function called multiple times
end
Are these equivalent in this example, or is the best implementation still calling a nested function?
Do the same arguments still hold when we are using C++ interface functions (custom generated with clibgen)?
  11 Comments
Cristian Le
Cristian Le on 27 Jan 2021
The problem with clibgen generated classes and functions is that they don't produce a .m file which can be editted. I can give a more practical example of something I'm working on:
For this I am trying to calculate fmincon with the objective and constraint taken from a C++ interface. Let's just take the constraint
// C++ code:
void class::nonlcon(double* x, double* c, int n_x, int n_c){
// assign c values here
...
}
After building the class and methods, we only have the following interface methods:
% Matlab side:
% You first need to construct the object
obj = clib.Proj.class();
% Interface method:
n_c = 2;
x = [1;2;3;4];
c = obj.nonlcon(x,n_c);
Now if we want to apply it into the fmincon we have to pass the value n_c as well. In this case we cannot use file functions because the object has to be created for the method to be defined. If the method is static, then yes that method would be similarly efficient.
Another point I've found is that when we use syntax like @obj.nonlcon, the function is called as an anonymous function and not as a function_handle, but I guess that makes sense since the object has to be passed as well. If there are any ways to improve this part I'm all ears.

Sign in to comment.


broken_arrow
broken_arrow on 20 Mar 2021
That leaves me a bit confused. Isn't an inlined function the same as just pasting the function code into a script (which would mean a script should be the most performant)? This post on the other hand suggests that functions are generally faster than scripts: https://de.mathworks.com/matlabcentral/answers/415728-details-on-why-functions-are-faster-than-scripts But if I pass variables to a function, the program would still have to look up the variables in the base workspace and launch the function, which creates overhead compared to a script. My "working hypothesis" used to be that everything that is executed only once is put in a script and functions are for code that is used often...
  23 Comments
Bruno Luong
Bruno Luong on 24 Mar 2021
My own reading of such description is that
  • old JIT is separated to EE and consisiting of calling prebuilt library to replace MATLAB code,
  • new JIT is integrated into EE and is close to a compilation to native machine instructions.

Sign in to comment.

Products


Release

R2009a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!