3
$\begingroup$

I have a function that I want to Compile into C for speed. Inside this function is a certain long expression called x, which has been computed earlier in a Mathematica session. However, if you call x naively inside the code, then you are referring to an "external variable" and so ordinary Wolfram Language code is used instead.

See below. The second version is 100 times faster because it got properly compiled into C. How can I include x in the code without literally copying-and-pasting a huge expression, which muddies up my notebook?

x = Sin[i^2]*Cos[i] (* A fairly long complicated expression *);
compiledsum1 = Compile[{{NumPoints, _Integer}}, 
   Block[
    {i, sum = 0.0},
    For[i = 0, i < NumPoints, i++, sum += x;];
    sum
    ], CompilationTarget -> "C"];
compiledsum2 = Compile[{{NumPoints, _Integer}}, 
   Block[
    {i, sum = 0.0},
    For[i = 0, i < NumPoints, i++, sum += Sin[i^2]*Cos[i];];
    sum
    ], CompilationTarget -> "C"];

Timings:

compiledsum1[100000] // Timing
{0.841049, 223.296}
compiledsum2[100000] // Timing
0.006448, 223.296
$\endgroup$
2

2 Answers 2

4
$\begingroup$

Pattern matching is your friend:

x = Sin[i^2]*Cos[i] (*A fairly long complicated expression*);
compiledsumtest1 = 
  Hold@Compile[{{NumPoints, _Integer}}, 
      Block[{i, sum = 0.0}, For[i = 0, i < NumPoints, i++, sum += x;];
       sum], CompilationTarget -> "C"] /. OwnValues@x // ReleaseHold;

Of course the solution above isn't the simplest for your specific problem. Henrik and I.M. have already shown two simpler solutions, I'd like to add one more based on pure function:

x = Sin[i^2]*Cos[i] (*A fairly long complicated expression*);
compiledsumtest2 = 
  Compile[{{NumPoints, _Integer}}, 
     Block[{i, sum = 0.0}, For[i = 0, i < NumPoints, i++, sum += #;];
      sum], CompilationTarget -> "C"] &@x;

But do remember the pattern-matching-based method is more general, here's an example.

$\endgroup$
3
  • $\begingroup$ Thank you! Can you point me to the best reference to understand all of this wizardry? The documentation is quite tricky for me to properly grasp. $\endgroup$ Sep 12, 2021 at 13:04
  • 1
    $\begingroup$ @BruceBartlett You may have a look at Leonid Shifrin's book, that's where I first learned about @, OwnValues, etc. These days Stephen Wolfram's book is a good choice, too. $\endgroup$
    – xzczd
    Sep 12, 2021 at 13:17
  • $\begingroup$ Thank you very much!! $\endgroup$ Sep 12, 2021 at 13:35
6
$\begingroup$

Even easier with With.

 compiledsum3 = With[{x = x},
  Compile[{{NumPoints, _Integer}}, 
   Block[{i, sum = 0.0}, 
    For[i = 0, i < NumPoints, i++, sum += x;]; 
    sum
   ], 
   CompilationTarget -> "C"]
 ]

(This is certainly a duplicate, but I have no time to look it up...)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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