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.

sorry for posting multiple questions about compile, but this is giving me some headache lately. This time my question is about using globally defined variables in a compile statement.

The problem is that when I define a compiled function that uses a global variable like this:

a = 1; (*global variable*)
GlobalVariableCompile = Compile[{{n, _Integer}}, For[i = 1, i < n, i++, a + Cos[i*Pi] + Sin[i*Pi]]];

The function is way slower then the noncompiled version:

GlobalVariable[n_] := For[i = 1, i < n, i++, a + Cos[i*Pi] + Sin[i*Pi]];

which can be easily verified by calling for example:

AbsoluteTiming[GlobalVariableCompile[100000];]
AbsoluteTiming[GlobalVariable[100000];]

What is the reason for this and how can I fix it?

My current solution: My solution right now is to define an additional parameter of the compiled function and pass the global variable a, then everything is very fast as expected (way faster than the noncompiled version):

GlobalVariableCompile = Compile[{{n, _Integer},{a, _Real}}, For[i = 1, i < n, i++, a + Cos[i*Pi] + Sin[i*Pi]]];
AbsoluteTiming[GlobalVariableCompile[100000,a];]
share|improve this question
1  
This sounds like a duplicate. Did you search first? Edit: I was probably thinking of (31171) which is not the same. Still looking for other relatives. –  Mr.Wizard Sep 4 '13 at 9:43
    
Could you describe how you intend to use your function? For example will it be applied many times with the same a value? If that is the case you could rebuild the compiled function when it is called. –  Mr.Wizard Sep 4 '13 at 9:54
    
@Mr.Wizard I don't recall a question on localization of variables in Compile, except perhaps the one by you, which is not exactly the same. It may be good to have a separate question discussing this, and what happens when the variables are not localized, and why. –  Leonid Shifrin Sep 4 '13 at 9:57
    
@Leonid Yes, I believe I was mistaken about the duplicate unless it's on Stack Overflow. I was hoping you'd show up to answer this as you're far better with Compile than I am. –  Mr.Wizard Sep 4 '13 at 10:00
1  
@Mr.Wizard I'd like to, but I've been quite busy recently, and also now. Basically, upon a superficial look at the code, it is a matter of variable localization (using Module or Block inside Compile). If this is not done, those variables are considered global by Mathematica. They are then not compiled, and every time they are accessed, there is a call to the main evaluator, which is the reason for the slowness. –  Leonid Shifrin Sep 4 '13 at 10:06

2 Answers 2

up vote 2 down vote accepted

Create a function with argument a that returns a CompiledFunction:

mkCF[a_] := 
  Compile[{{n, _Integer}}, 
   For[i = 1, i < n, i++, a + Cos[i*Pi] + Sin[i*Pi]]];
cf = mkCF[1];
AbsoluteTiming[cf[100000];]

Inspecting the CompilePrint reveals that there are calls to the evaluator:

Needs["CompiledFunctionTools`"]
CompilePrint[cf]

which should be removed if you need performance. For example:

mkCF2[a_] := 
  Compile[{{n, _Integer}}, Do[a + Cos[i*Pi] + Sin[i*Pi], {i, n}]];
cf2 = mkCF2[1];
AbsoluteTiming[cf2[100000];]

There are no calls to the evaluator left:

CompilePrint[cf2]

As for performance:

AbsoluteTiming[r1 = GlobalVariable[100000];]
AbsoluteTiming[r2 = cf2[100000];]
(*
{1.009310, Null}
{0.054743, Null}
*)

and

r1 == r2
(*True*)
share|improve this answer
    
Thank you very much, that was enlightening. –  Wizard Sep 4 '13 at 11:34

Based on your comment:

I intend to set the global variable a once and not change it over the whole course of the calculation. So basically a can be treated as a global constant.

I believe you merely need to inject the value of a and properly localize i. These actions can be done with With and Module respectively:

a = 1;

With[{a = a},
 GlobalVariableCompile =
   Compile[{{n, _Integer}},
     Module[{i},
       For[i = 1, i < n, i++, a + Cos[i*Pi] + Sin[i*Pi]]
     ]
   ]
]

With[{a = a}, body] directly substitutes the global value of a for any explicit appearance of the Symbol a in body. More significant to the speed of your code Module[{i}, body] defines i as a variable local to Compile.

ruebenko's use of Do fixes the second problem because Do uses Block-like scoping of its iterators, so they are already localized.

share|improve this answer

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.