Let me elaborate my comment into an answer. To make the nested Sum
compiled, let's first have a close look at the compiling result of code containing one Sum
:
sum = Compile[{{n, _Integer}}, 1/Sum[3.141 + j, {j, n}]];
Needs["CompiledFunctionTools`"]
p1 = CompilePrint@sum
It's not hard to notice that Sum
is actually translated into a loop by Compile
. It's reasonable to guess, if we express the summation with a loop instead of Sum
, it will be finally translated into the same result, and it's true:
sum2 = Compile[{{n, _Integer}}, Module[{k = 0.}, 1/(Do[k += 3.141 + j, {j, n}]; k)]];
p2 = CompilePrint@sum2;
Grid[{{p1, p2}}, Frame -> All]
You can see the compiling results are almost same.
Manually replacing Sum
with Module[…, Do[…]]
is tedious, let's make use of code generation technique to facilitate the replacement:
sum[expr_, iter_] := Module[{k = 0.}, Do[k += expr, iter]; k];
sum2test = Hold@Compile[{{n, _Integer}}, 1/sum[3.141 + j, {j, n}]] //. DownValues@sum //
ReleaseHold;
sum2test@1000 == sum2@1000
(* True *)
Then since the Module[… Do[… ]]
algorithm is closer to the the one adopted inside Compile
, it's reasonable to guess that Compile
can translate it more easily i.e. it may be compiled successfully in a situation that Sum
fails, for example, nested Sum
, and again, it's true:
sumsum2 = Hold@Compile[{{n, _Integer}}, sum[1/Sum[i + j, {j, n}], {i, n}]] //.
DownValues@sum // ReleaseHold;
CompilePrint@sumsum2
Pictured by Simon Wood's shadow.
Now the code is completely compiled and I believe it had the same performance as the compiled nested Sum
(if it was correctly compiled).
Another acceptable solution is
sumsum3 = Compile[{{n, _Integer}}, Total@Table[1/Sum[i + j, {j, n}], {i, n}]];
It's a little faster than sumsum2
:
sumsum3[10^4] // AbsoluteTiming
sumsum2[10^4] // AbsoluteTiming
{4.073000, 0.000109848}
{4.156000, 0.000109848}
However, what I really want to say is, I believe a nested Sum
is not the fastest solution for your original problem at all, considering the facts that most of the arithmetic functions in Mathematica are Listable
and taking advantage of the vectorization is one of the most important approaches to speed up codes even inside Compile
. Here's a vectorized version of your toy code:
sumsum0 = Compile[{{n, _Integer}}, Total[1/(n Range@n + Total@Range@n)]];
sumsum0[10^4] // AbsoluteTiming
{0.001000, 0.000109848}
Sum
can be written assumsum = Compile[{{data, _Real, 1}, {n, _Integer}}, Module[{t = Total@data[[;; n]]}, Total[(1/(n data[[;; n]] + t))]]]
$\endgroup$Sum
can be generally avoided. BTW, according to my quick test,Plus@@Table
is faster thanSum
, andTotal@Table
will be even faster. $\endgroup$