why wrapping with anonymous function speeds up?
Afficher commentaires plus anciens
I try to understand the rational behind this result. When I wrap a function within an anonymmous function, it runs almost 10 times faster (R2022a, Windows, my PC, slightly less on remote server) !
What's going on ?
testfunctioncall()
function testfunctioncall
nruns = 1e6;
a = 1;
b = 2;
%%
fun = @add;
tic;
for k=1:nruns
c = fun(a, b);
end
t1=toc;
% time with direct 1000000 calls of "add" = 0.729264 [s]
fprintf('time with direct %d calls of "add" = %f [s]\n', nruns, t1);
%%
fun = @(a,b) add(a,b);
tic;
for k=1:nruns
c = fun(a, b);
end
t2=toc;
% time with 1000000 calls of "add" wrapped in anonymous = 0.076203 [s]
fprintf('time with %d calls of "add" wrapped in anonymous = %f [s]\n', nruns, t2);
end % testfunctioncall
%% subfunction
function c = add(a, b)
c = a + b;
end
4 commentaires
That is odd.
I added a bit more cases to see if I could explain it, but I was not able to come up with a reason.
One hypothesis was that perhaps the constants being passed in was allowing some optimization, so I feed in different inputs each time, but that did not make any substantial difference.
The "retry" is there because sometimes timing is a bit odd the first time you do something in MATLAB; sometimes you need to run a second time to get the "sustainable" timing. You can see here that the retry was faster, but not by orders of magnitude like the anonymous function is.
I have seen in the past that using anonymous functions is often considerably slower than @ of a function directly by name. I am not sure what is happening in this case.
testfunctioncall()
function testfunctioncall
nruns = 1e6;
a = rand(nruns,1);
b = rand(nruns,1);
%%
fun = @add;
start = tic;
for k=1:nruns
c = fun(a(k), b(k));
end
t1=toc(start);
% time with direct 1000000 calls of "add" = 0.729264 [s]
fprintf('time with direct %d calls of "add" = %f [s]\n', nruns, t1);
%%
fun = @(a,b) add(a,b);
start = tic;
for k=1:nruns
c = fun(a(k), b(k));
end
t2=toc(start);
% time with 1000000 calls of "add" wrapped in anonymous = 0.076203 [s]
fprintf('time with %d calls of "add" wrapped in anonymous = %f [s]\n', nruns, t2);
fun = @plus;
start = tic;
for k=1:nruns
c = fun(a(k), b(k));
end
t3=toc(start);
fprintf('time with %d calls of "plus" in @ = %f [s]\n', nruns, t3);
start = tic;
for k=1:nruns
c = plus(a(k), b(k));
end
t4=toc(start);
fprintf('time with %d calls of "plus" direct = %f [s]\n', nruns, t4);
start = tic;
for k=1:nruns
c = a(k) + b(k);
end
t5=toc(start);
fprintf('time with %d direct + calls = %f [s]\n', nruns, t5);
fun = @(a,b) add(a,b);
start = tic;
for k=1:nruns
c = fun(a(k), b(k));
end
t2=toc(start);
% time with 1000000 calls of "add" wrapped in anonymous = 0.076203 [s]
fprintf('retry time with %d calls of "add" wrapped in anonymous = %f [s]\n', nruns, t2);
end % testfunctioncall
%% subfunction
function c = add(a, b)
c = a + b;
end
Bruno Luong
le 30 Mar 2022
Modifié(e) : Bruno Luong
le 30 Mar 2022
Stephen23
le 30 Mar 2022
A wild stab in the dark: might this have something to do with resolving overloaded functions? Perhaps the anonymous function somehow optimizes selecting the correct function in a way that is not possible with the simple function handle.
Do non-overloaded functions show the same behavior?
Bruno Luong
le 30 Mar 2022
Réponses (1)
Fangjun Jiang
le 29 Mar 2022
Modifié(e) : Fangjun Jiang
le 29 Mar 2022
Don't know the exact reason, but I guess it shows that "annonymous function handle" is faster than "named function handle". It is like macro vs function, or inline vs function call? I noticed that direct function call in this case is even faster.
function testfunctioncall
nruns = 1e6;
a = 1;
b = 2;
%%
fun = @add;
tic;
for k=1:nruns
c = fun(a, b);
end
t1=toc;
% time with direct 1000000 calls of "add" = 0.729264 [s]
fprintf('time with direct %d function handle calls of "add" = %f [s]\n', nruns, t1);
%%
fun = @(a,b) add(a,b);
tic;
for k=1:nruns
c = fun(a, b);
end
t2=toc;
% time with 1000000 calls of "add" wrapped in anonymous = 0.076203 [s]
fprintf('time with %d calls of "add" wrapped in anonymous = %f [s]\n', nruns, t2);
tic;
for k=1:nruns
c = add(a, b);
end
t3=toc;
% time with 1000000 calls of "add" wrapped in anonymous = 0.076203 [s]
fprintf('time with %d function calls of "add" = %f [s]\n', nruns, t3);
end % testfunctioncall
%% subfunction
function c = add(a, b)
c = a + b;
end
Catégories
En savoir plus sur Startup and Shutdown dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!