# How to compile sum over the compiled expression?

Consider the following toy code:

table = Table[{i^0.11, i^0.005}, {i, 1, 1000, 0.5}];
val = Compile[{{table, _Real, 2}, {i, _Integer}}, table[[i]][[1]], CompilationOptions ->
"InlineCompiledFunctions" ->
True, CompilationTarget -> "C"]
sum = Hold@
Compile[{{table, _Real, 2}},
Sum[val[table, i], {i, 1, Length[table], 1}], CompilationOptions ->
"InlineCompiledFunctions" ->
True, CompilationTarget -> "C", Parallelization -> True] /. OwnValues@val //
ReleaseHold


where I define compiled value val[table,i], and then compiled sum over i, sum[table]. I get error

Function::flpar: Parameter specification {table,1} in {table,1}\[Function]table[[1]][[1]] should be a symbol or a list of symbols.


Could you please tell me how to have the compile the sum over i? I need this since in realistic case table is also a (very complicated) compiled function, and I also cannot omit the intermediate definition val, as there are too many intermediate actions that I need to get in order to obtain val.

Inlining is really not Compile's strength. I got it working though by declaring an accumulator a and by replacing Sum by a Do loop.

table = Table[{i^0.11, i^0.005}, {i, 1, 1000, 0.5}];

val = Compile[{{table, _Real, 2}, {i, _Integer}},
CompileGetElement[table, i, 1],
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
];

sum = With[{val = val},
Compile[{{table, _Real, 2}},
Block[{a},
a = val[table, 1];
Do[a += val[table, i], {i, 2, Length[table], 1}];
a
],

CompilationTarget -> "C",
CompilationOptions -> {"InlineCompiledFunctions" -> True},
RuntimeOptions -> "Speed"
]
];


Note however that this is very inefficient, because Compile does not really inline; when tensors are involved, it typically adds a CopyTensor for each inlined call to val -- and that's just to extract a single number from the array. That means: "InlineCompiledFunctions" -> True enforces call by value! This is really a total performance killer for Compile and the reason why I moved to directly programming in C++ via LibraryLink for complicated work flows.

If you insist on using Compile (which I would understand because that was my own practice for a long time), then I would suggest to also measure the performance of "InlineCompiledFunctions" -> False. Depending on the workload, it might be faster even though not inlined.

Edit

Just to demonstate how inefficient this is, let's compare with the manually inlined version below:

sum2 = With[{val = val}, Compile[{{table, _Real, 2}},
Block[{a},
a = CompileGetElement[table, 1, 1];
Do[a += CompileGetElement[table, i, 1], {i, 2, Length[table],1}];
a
],
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
]
];


Here the comparison:

table = RandomReal[{-1, 1}, {100000, 10}];
result = sum[table]; // RepeatedTiming // First
result2 = sum2[table]; // RepeatedTiming // First
result == result2


0.872045

0.000093828

True

So the first version takes more than 50000(!) times longer.

• Why does the code use CompileGetElement[table, i, 1] rather than table[[i,1]] ? May 8 at 4:52
• Does your comment about CopyTensor mean that generally, computations involving matrices are slow with Compile? I am noticing that Compile is quite slow at building a 100x100x32x32 tensor (takes a few seconds) May 8 at 4:56
• "Why does the code use CompileGetElement[table, i, 1] rather than table[[i,1]]?" Because CompileGetElement skips the bound checks and is thus faster. May 8 at 5:53
• "Does your comment about CopyTensor mean that generally, computations involving matrices are slow with Compile?" There are a few workarounds, but in general yes, writing complicated code for multidimensional arrays is often more efficient when it is done with plain C code via LibraryLink instead with Compile. May 8 at 5:57