Borrar filtros
Borrar filtros

is 'arrayfun' faster much more than 'for' loop?

121 visualizaciones (últimos 30 días)
vx2008
vx2008 el 9 de Feb. de 2017
Comentada: Bruno Luong el 15 de En. de 2021
now I have written a function which use a 'for' loop and it runs slowly because of large calculations; If i use 'arrayfun' to replace 'for' loop, the function would run faster much?
  1 comentario
Adam
Adam el 9 de Feb. de 2017
Editada: Adam el 9 de Feb. de 2017
Simplest way to understand is to implement both options and time them using
doc timeit
I do this regularly when I want to understand which of multiple methods of implementing something is faster. As Walter says below though, if you just want a quick answer arrayfun is usually slower.

Iniciar sesión para comentar.

Respuestas (3)

Walter Roberson
Walter Roberson el 9 de Feb. de 2017
Typically arrayfun() runs more slowly, because it needs to invoke a function call each time through its internal for loop. There is still a for loop; it is just hidden.
  1 comentario
Walter Roberson
Walter Roberson el 12 de Feb. de 2017
Here is some code to test out various possibilities.
The items are:
  1. plain for loop
  2. arrayfun
  3. if false arrayfun else for loop
  4. arrayfun_is_faster = false; if arrayfun_is_faster arrayfun else for loop
  5. retest plain for loop
The code has two outputs: first the ratio of times relative to the plain for loop, and secondly the mean time of each of the groups.
The times will be plotted along with a mark indicating the mean time. The y limits are set the same on all of the plots so you can directly compare the height of the mean lines.
If you have the statistics toolbox a boxplot will be presented as well.
In my test, arrayfun is consistently the slowest, by 30% to 60%.
However, in my tests, the initial test of plain for loop was often the second slowest, even though the for loop logic is copied exactly the same to #3 and #4, measurably slower than re-running the exact same for loop after the other tests were done. Testing for a variable set false was about 1% slower than "if false": slower but not much slower.
Why was the initial running of the plain for loop slower than re-running it later? I notice that even though I re-run the timeit 200 times, the variability of timings on the first probe of plain for loops is much higher than later. I have no explanation for that.
I could hypothesize that the JIT has does not fully optimize until the code has been run a few hundred times (each timeit() call is going to call the actual routine a number of times.)

Iniciar sesión para comentar.


Jan
Jan el 9 de Feb. de 2017
Editada: Jan el 9 de Feb. de 2017
While in all of my tests arrayfun was slower, I have collected these tests in an M-file and run it with every new Matlab release. I'm used to write the for-loop approach at first, add the arrayfun afterwards and compare the results and speed by unit-testing. Then I comment out the slower method.
This demands for an exhaustive commenting, because it is too confusing, if somebody finds commented code some years later and has no idea, why it is not used. Or imagine that the arrayfun approach is modified later, but the commented for approach is not. This will confuse a reader massively, if it is not explained clearly.
Care for optimizing the bottlenecks only. So called premature optimization can increase the debug time dramatically, such that the total program time (programming + debugging + documenting + running) might increase.
Summary: Try it.
  3 comentarios
Jan
Jan el 11 de Feb. de 2017
Editada: Jan el 11 de Feb. de 2017
While the time penalty will be tiny, the 2nd version will save minutes or more by avoiding speculations during debugging.
Walter Roberson
Walter Roberson el 12 de Feb. de 2017
Looks like less than 1% penalty for "if arrayfun_is_faster"

Iniciar sesión para comentar.


Arjan Lampe
Arjan Lampe el 6 de Mayo de 2020
It seems arrayfun is much, much more slower. Or am I messing something up?
A simple (too simple?) test. Make some test function:
testf.m:
function m = testf(m)
%TESTF Summary of this function goes here
% Detailed explanation goes here
for c_m = 1:numel(m)
m(c_m) = sqrt(m(c_m));
end
end
And then:
>> m = rand(15)
>> tic; for ii = 1:1000000; testf(m); end; toc
Elapsed time is 1.405036 seconds.
>> tic; for ii = 1:1000000; arrayfun(@sqrt,m); end; toc
Elapsed time is 116.857802 seconds.
That is a factor 83 slower...
  2 comentarios
Evan Voyles
Evan Voyles el 15 de En. de 2021
I think the factor for which it is slower largely depends on what function you are applying to the array. For example, I tested arrayfun vs a forloop, squaring the elements, and the speed difference was a factor of two. While this is concrete evidence that we should always use for loops instead of arrayfun, it's obvious that the benefit varies.
It's kind of sad because writing a single command arrayfun is so much more appealing that writing out the full for loop. I guess that's the sacrifice that we make for performance ;)
Bruno Luong
Bruno Luong el 15 de En. de 2021
twice only? Put it in a function to have JIT correctly speed up the loop
function forloopvsarrayfun
x = rand(1,1e6);
tic
y = zeros(size(x));
for i=1:length(x)
y(i) = x(i).^2;
end
t1=toc;
tic
y = arrayfun(@(x) x.^2, x);
t2=toc;
fprintf('for loop time = %g\n', t1);
fprintf('arrayfun time = %g\n', t2);
fprintf('arrayfun time is %g time slower\n', t2/t1);
end
This is the result with R2020B
for loop time = 0.0042138
arrayfun time = 1.99038
arrayfun time is 472.348 time slower

Iniciar sesión para comentar.

Categorías

Más información sobre Loops and Conditional Statements en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

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

Start Hunting!

Translated by