Let's say I have a list of random numbers;
list = Table[Random[], {100000}];
I want to apply a function f
in every element of the list and take their sum. An obvious solution to that would be
Total[f[list]]
For the sake of clarity I am using here the following simple f
:
f=#^2&;SetAttributes[f, Listable]
(Of course, the function Power
is Listable
by default
Do[Total[f[list]],{100}]//AbsoluteTiming
outputs 0.158
on my machine.)
But as always I want the fastest routine I can get. So I used Compile
to reduce the running time:
fc=Compile[{{list,_Real,1}},Total[f[list]]];
Testing with
Do[fc[list],{100}]//AbsoluteTiming
I got a worse result, namely 0.288
! :-(
I tested again putting f
by hand inside the compiled function:
fcfast=Compile[{{list,_Real,1}},Total[list^2]];
Do[fcfast[list], {100}] // AbsoluteTiming
Output was 0.054
and I was pleased!
Why is this happening? How can I speed up my routines without having to put the function explicitly inside Compile
?
Sjoerd C. de Vries answered on the question Using Apply inside Compile tracing with Needs["CompiledFunctionTools"]
and the function CompilePrint
that explains the timing differences but I still don't know how to improve that.
Results after applying the best solution :
I am adding here my test results using for various implementations. I added CompilationOptions -> {"InlineExternalDefinitions" -> True}
which answered my question.
The list i used contained 1000000 random numbers , f=#^2&
and the compiler used was the MinGW.
Goto
andCompile
and does not deal with timing. $\endgroup$f=#^2&;SetAttributes[f, Listable]
does not achieve what you expect, the attributes off
don't influence how the pure function is evaluated. You woul instead wantf=Function[Null,#^2,Listable]
. Of course, as you mentioned, here it doesn't make a difference sincePower
is listable anyway. You can see the difference when using any function that isn't listable instead ofPower
... $\endgroup$