I was investigating how Fold
could improve performance vs Do
. I tested the code
AbsoluteTiming[
sum = 1.0;
inc = 1.0;
Do[inc = inc*Sin[10.5]/i; sum = sum + Tan[inc], {i, 10^5}];
sum]
The output is
Out[] = {2.303896, 0.105747}
I have hoped that using Fold
could improve the performance:
AbsoluteTiming@
Fold[{#[[1]]*Sin[10.5]/(#2 + 1), #[[2]] + Tan@#[[1]]} &,
{Sin[10.5], 1.0}, N@Range[10^5]]
However, this code is not faster:
Out[] = {2.471189, {-5.537337857006675*10^-462146, 0.105747}}
I have some questions concerning the above example:
(1) [Partially solved. See EDIT] Why the Fold
here is not faster? I thought it should have been auto-compiled and thus faster. But it didn't.
(2) [Solved. See EDIT] Here Mathematica is using precision much higher than double precision (by having number as small as 10^{-462146}). Would it be possible to set precision to boost performance? I tried SetPricision
and SetAccuracy
. The precision changes but it doesn't improve performance.
(3) [Solved. See Mr. Wizard's example in his answer] Another problem of Fold
is that one has first to generate a long list (length 10^5 in this example). For much larger list, the Fold
method may use too much memory. Is it possible to use functional way (not necessarily Fold
) in a more memory-efficient way?
Thank you very much!
PS: I met this question when trying to reproduce Mr.Wizard's answer of the below thread, with some modifications. I can reproduce Wizard's result, where Fold
boots the performance greatly compared with Do
. But I don't understand why my above example is not as good.
Alternatives to procedural loops and iterating over lists in Mathematica
EDIT:
(a) Rojo's comment is the answer of (2): SetSystemOptions["CatchMachineUnderflow" -> False]
(b) About the performance of Fold: on Mathematica v7 after disabling CatchMachineUnderflow
, the Fold code is 10x faster then Do code. However, on Mathematica v9 the Fold code is a bit slower than Do. This seems like a regression in Mathematica. For comparison, this code has 10x improvement than the Do version: Fold[# + Sin[#2] &, 1.0, Range[10^6]]
both on v7 and v9.
"FoldCompileLength" -> 100
? As detalied here mathematica.stackexchange.com/a/1816/745. Also your function can easily be compiled manually, giving you more control (for example you can compile to C etc...) $\endgroup$SetSystemOptions["CatchMachineUnderflow" -> False]
to avoid the low numbers $\endgroup$