4

I've noticed that if I try to define a Function within a Module within Compile, I get errors of (* Compiled expression Function[...] should be a machine-size real number *) IF those functions are local variables within the Module AND I don't assign the Module itself to a variable name within Compile. Weird, no? I know about using the trailing ..., {{Pattern, _Type}} syntax, but I don't think that's applicable here (besides, I'm not sure that a type of Function is listed in the supported types, anyways... -- yet it does appear that they can be used within Compile).

I'm still too new to Compile to know whether putting the Functions within a Module is even advised, but I read elsewhere that using symbols that aren't shielded within something like a Module causes calls to MainEvaluate[], which considerably slows performance.

Any idea why this happens?

Compile[{},
  f1 = Function[{}, 1.0]; (* Fine! *)
  f2 = 1.0 &; (* Fine! *)

Module[{f3, f4}, (f3=Function[{},1.0];) (* ABOVE: Compiled expression Function[{}, 1.`] should be a machine-size real number ) (f4=1.0&;) ( Same ) f5 = Function[{}, 1.0]; ( Fine! ) f6 = 1.0 &; ( Fine! ) {f5[], f6[]} ]; mod = Module[{f7, f8}, f7 = Function[{}, 1.0]; ( Fine! ) f8 = 1.0 &; ( Fine! *) {f7[], f8[]} ]; mod ][] ```

Sean
  • 645
  • 4
  • 10

2 Answers2

3

I think I answered my own question via CompilePrint (just learned about this); will post for posterity:

ClearAll[f1, f2, f3, f4, f5, f6, f7, f8]
f3 := Function[y, y^4];
c1 = Compile[{x},
   m1 = Module[{f1},
     f1 = Function[y, y^2];
     f1[x]
     ];
   Module[{},
    {Function[y, y^3][x], f3[x]}
    ]
   ];
c1[2]
m1
Needs["CompiledFunctionTools`"]
CompilePrint[c1]
1   V17 = MainEvaluate[                                                 \
  2
Function[{x}, m1 = Module[{f1}, f1 = Function[y, y ]; f1[x]]][ R0]]
2   R2 = R0
3   R1 = Power[ R2, I0]
4   R2 = MainEvaluate[ Hold[f3][ R0]]
5   T(R1)0 = {R1, R2}
6   Return

It looks like the versions that I thought were "working" were just running in non-compiled mode (not just the assignments, either -- the whole step). I'm used to getting an error/warning in such cases, but I had to look at CompilePrint to see it this time.

I guess you just have to use anonymous functions exclusively. It looks like BOTH the methods in my original post AND defining the Function outside of Compile altogether (as I indicated I was unsure-about in my original post) cause MainEvaluate[] to be used...

I could've sworn I'd come across other examples on StackOverflow where a function was defined outside of Compile and then used within it, but I'll have to educate myself further.

Sean
  • 645
  • 4
  • 10
  • https://mathematica.stackexchange.com/questions/145991/what-can-be-inlined-by-inlineexternaldefinitions-true – b3m2a1 Jan 08 '21 at 05:29
3

In your case using With is enough:

With[{f3 = Function[y, y^4], f1 = Function[y, y^2]},
c1 = Compile[{x},
       f1[x];
       {Function[y, y^3][x], f3[x]}   
     ]
];
Needs["CompiledFunctionTools`"]
compiledOKQ = StringFreeQ[CompiledFunctionTools`CompilePrint[#1], "MainEvaluate"]&;
compiledOKQ[c1]

gives True

Rolf Mertig
  • 17,172
  • 1
  • 45
  • 76