Verbeia opened up a rather interesting discussion on the performance of the functional programming style in Mathematica. It can be found here: What is the most efficient way to construct large block matrices in Mathematica?)
I’m working on a problem, and after doing some timing of my code one particularly time consuming portion is where I calculate entries of a matrix through a recurrence relation:
c = Table[0, {2L+1}, {2L+1}];
c[[1, 1]] = 1;
Do[c[[i, i]] = e[[i - 1]] c[[i - 1, i - 1]], {i, 2, 2 L + 1}];
Do[c[[i, 1]] = (1 - e[[i - 1]]) c[[i - 1, 1]], {i, 2, 2 L + 1}];
Do[c[[i, j]] = (1 - e[[i - 1]]) c[[i - 1, j]] +
e[[i - 1]] c[[i - 1, j - 1]], {i, 2, 2 L + 1}, {j, 2, i - 1}];
Where e is some externally defined list. Is there any way I could write this in a more efficient manner? I can’t seem to find any obvious way of using the built in functions to accomplish this in a more idiomatic and efficient way.
I realize I can only do so much, since this code is O(n^2), but I have a series of matrix multiplications (About 6 in all) that, combined, take less time to run than this statement. Anything I can do to speed this up even slightly would make an appreciable difference in run times for me.
Update:
In line with what acl recommended, I tried using Compile to speed up my expressions. For a relatively small L = 600, I get 3.81 seconds on the naive Do[...], 1.54 seconds for plain old Compile, and 0.033 seconds for Compile[..., CompilationTarget->"C"].
For a more realistic size of L = 1200, the timings become 16.68, 0.605, and 0.132 for Do, Compile and Compile[.., CompilationTarget->"C"] respectively. I’m able to achieve the same 2 orders of magnitude speedup that acl mentioned in his post.
Try
Compile. Here I define 3 functions:fas you defined it,fccompiled (to some sort of bytecode) andfcccompiled to C (look up the documentation as to how to examine the generated code).First, make mma tell us if something can’t be compiled:
then the functions:
no errors, so it’s OK. And now test (these on a macbook with a 2.4GHz core 2 duo running on battery):
giving
so the version compiled to C is two orders of magnitude faster here.
If you change the types and get compilation errors, ask.
EDIT: If
econtains reals, tryinstead.
One can get a feel for how this works by saying
and obtaining
with the names of the registers indicating their type etc. You can also look at the generated C code if you use the “C” option (but that is a bit harder to read).