On 4/1/10 at 5:59 AM, sheaven at gmx.de (sheaven) wrote:
>I am new to Mathematica and try get a understanding of its power. I
>plan to use Mathematica mainly for financial data analysis (large
>lists...).
>Currently, I am trying to optimize calculation time for calculations
>based on some sample data. I started with with a moving average of
>share prices, because Mathematica already has a built in moving
>average function for benchmarking.
>I know that the built-in functions are always more efficient than
>any user built function. Unfortunately, I have to create functions
>not built in (e.g. something like "moving variance") in the future.
>I have tried numerous ways to calc the moving average as efficiently
>as possible. So far, I found that a function based on Span (or
>List[[x;;y]]) is most efficient. Below are my test results.
>Unfortunately, my UDF is still more than 5x slower than the built in
>function.
>Do you have any ideas to further speed up the function. I am already
>using Compile and Parallelize.
>This is what I got so far:
>1. Functions for moving average:
<function code snipped>
>2. Create sample data: data = 100 + # & /@
>Accumulate[RandomReal[{-1, 1}, {10000}]];
a side point here. The plus function works on lists. That is:
data = 100 + Accumulate[RandomReal[{-1,1}, 10000]];
will produce the same result as your code but be a bit faster.
Note, the difference in speed here will be quite small and is
clearly not the thrust of your message. But I point this out
since such small difference can add up to something significant
in more complex code.
>3. Test if functions yield same results: Test1 = movAverageC[data,
>30, 250, 10]; (*Moving average for 30 days to 250 days in steps of
>10*)
OK. Here is the timing results I get for you compiled code based
on Span
In[1]:= movAverageOwn2FC =
Compile[{{dataInput, _Real,
1}, {days, _Integer}, {length, _Integer}},
N[Mean[dataInput[[1 + # ;; days + #]]]] & /@
Range[0, length - days, 1]];
In[2]:= data = 100 + Accumulate[RandomReal[{-1, 1}, {10000}]];
In[3]:= Timing[Table[movAverageOwn2FC[data, 20, Length@data], {100}];]
Out[3]= {1.45855,Null}
Now here is a definition using ListConvolve
In[4]:= newMoveAverage[data_, windowLen_] :=
Module[{ker = Table[1, {windowLen}]/windowLen},
ListConvolve[ker, data]]
In[5]:= Timing[Table[newMoveAverage[data, 20], {100}];]
Out[5]= {0.103379,Null}
So, on my machine using a single core without Compile, using
ListConvolve improves the speed by more than 10X. Using both
parallel processing with both cores should improve this result
for very large data arrays. Note, ListConvolve is so fast, the
overhead of setting up parallel processes will probably degrade
times for small data arrays. I have not tested this to verify my
guess here.
Compile also might improve things somewhat. But this probably
won't be significant. Compile can offer significant improvement
in some code particularly when procedural programming is used.
But compile seldom offers improvement in code with one or two
function calls and no procedural structures such as For. In
fact, there are times when using Compile will actually degrade
the execution speed.
Finally, to demonstrate the code with ListConvolve does the same
as your code:
In[6]:= movAverageOwn2FC[data, 20, Length@data] ==
newMoveAverage[data, 20]
Out[6]= True