Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have simple function I would like to compile, but I get a warning and a call to MainEvaluate. I would like to avoid both.

ClearAll[MakeInPeriodicCell]
On["CompilerWarnings"]
MakeInPeriodicCell = 
  Compile[{x, cellwidth}, 
   First@Sort[{x, x - cellwidth, x + cellwidth}, Abs[#1] < Abs[#2] &]];
CompiledFunctionTools`CompilePrint[MakeInPeriodicCell]  

(*Compile::noinfo: No information is available for compilation of 
Sort[{x,x cellwidth,x+cellwidth},Abs[#1]<Abs[#2]&]. 
The compiler will use an external evaluation and make assumptions about the return type.*)

(*
...
5   T(R1)2 = MainEvaluate[ Function[{x, cellwidth}, Sort[{x, x - \
cellwidth, x + cellwidth}, Abs[#1] < Abs[#2] & ]][ R0, R1]]
...
*)

EDIT

(I got the correct syntax for the subexpression from an answer that got deleted?) I tried setting the type of a subexpression like this:

MakeInPeriodicCell = 
 Compile[{x, cellwidth}, 
  First@Sort[{x, x - cellwidth, x + cellwidth}, 
    Abs[#1] < Abs[#2] &], {{Sort[_,_], _Real,1}}]

This gets rid of the warning, but the call to MainEvaluate remains.

Can this snippet be compiled without a call to MainEvaluate?


EDIT 1

Since compile is always about speed, here is some benchmark info. (the code is here, as it clutters the question a bit)

data = RandomReal[{-100, 100}, 100000];
(*Original implementation*)
m0 = MakeInPeriodicCellOrig[data, 30]; // AbsoluteTiming (*0.8370473*)
(*my revritten*)
m1 = MakeInPeriodicCellImp[data, 30]; // AbsoluteTiming  (*0.0360021*)
(*F'x answer*)
m2 = MakeInPeriodicCellFx[data, 30]; // AbsoluteTiming   (*0.0140008*)

m0 == m1 == m2 (*True*)

So getting read of MainEvaluate gives you about 20x speed-up and changing to a better algorithm another 3x. I usually have a million to ten million points, so the speed-up is very welcome.

share|improve this question
    
If you set SetSystemOptions["CompileOptions" -> "CompileReportExternal" -> True] the warning does not go away. Out of curiosity, have you read these two questions? –  rcollyer Apr 5 '12 at 15:36
    
@rcollyer But of course I have read the two questions:) –  Ajasja Apr 5 '12 at 15:39
    
I had to ask. :) –  rcollyer Apr 5 '12 at 15:41
    
I did figure out what the problem is: Function[] is not in the compilable list. But I didn't notice it before, since it was hidden in the short form &. Should I post the answer or just delete the whole question? –  Ajasja Apr 5 '12 at 15:43
    
@Ajasja one could post a workaround as an answer; I don't see why to delete the question –  acl Apr 5 '12 at 15:44

2 Answers 2

up vote 5 down vote accepted

I think Leonid’s comment is spot on. You could work around the issue with a completely different approach:

MakeInPeriodicCell = Compile[{{x, _Real}, {cellwidth, _Real}},
   If[x < -(cellwidth/2.), x + cellwidth, 
    If[x > cellwidth/2., x - cellwidth, x]]
   ];
share|improve this answer
2  
Could also use Ordering and order Abs of your list, and then extract elements - this way one can use default comparison function and compile. –  Leonid Shifrin Apr 5 '12 at 15:48

It appears that in this case Function[] can not be compiled without a call to MainEvaluate.

This is my workaround, but I like F'x much better:)

MakeInPeriodicCell = Compile[{x, cellwidth},
  With[{  l = {x, x - cellwidth, x + cellwidth}},
   Sort[Transpose[{Abs[l], l}]][[1, 2]]
   ]]
share|improve this answer
1  
This is not a problem of Function not being compiled, this is a problem of type-inferencing inside Sort. I suspect that this is a flaw or limitation of how compilation of Sort was implemented, and has nothing to do directly with abilities of Compile to compile pure functions. –  Leonid Shifrin Apr 5 '12 at 15:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.