This may not be so much of a scientific computing question but more of a MATLAB question, if that is the case, please feel free to close or migrate the question.
Root-finding problems are commonly encountered in scientific computing in various shapes and forms; but in this case, the goal is to solve a non-linear time-dependent PDE using operator splitting techniques. Without going into the details of the PDE problem (since it is irrelevant to my main question), the following lines are executed each time step:
S = arrayfun(@(x,y) fsolve(@(c)[x-c(1)-c(1)*c(2);y-c(1)*c(2)],rand(1,2),options),u,v, ...
'UniformOutput',false);
options is a structure to set the parameters of fsolve, u and v are column vectors of medium size (~8k or larger) and fsolve returns a vector (1 row by 2 columns) which necessitates the option (for arrayfun) UniformOutput to be set false. I can replace these two lines with the following for loop:
for i=1:length(u)
S(i,:) = fsolve(@(c)[u(i)-c(1)-c(1)*c(2);v(i)-c(1)*c(2)],rand(1,2),options);
end
This excerpt runs two times faster than the previous. The time difference even more significant if S is initialized ahead of time and transposed (so it aligns with column-major ordering of MATLAB). Apparently, this behaviour is expected since arrayfun just “hides” (internalizes) the for loop, and we have additional overhead introduced by the extra function handle.
Under this observation, what is the correct use case for the function arrayfun? If for loops are faster, why would someone use arrayfun? Especially when (arguably) for loops are easier to read?
Note: There are some nuances. For example, S as the output of arrayfun is a cell array in contrast to the n-by-2 matrix S we get from the for loop approach. So let's say that I don't care about the output, it could as well be dumped after computation. I am more interested in the reasons why someone would use arrayfun over a for loop given that arrayfun is 2x slower.
Edit 1: Octave gives the following justification for arrayfun's existence: "This is useful for functions that do not accept array arguments.". But then follows up with "If the function does accept array arguments it is better to call the function directly. ", since they also only internalize the for loop. And at the end of the documentation, they say that the built-in @plus function is 60% faster than the anonymous function @(x,y) x+y
. This is probably because @plus behaves more like C macros, so there is no additional function call overhead.