This question is tightly related to the answer Shaving the last 50 ms off NMinimize.
There @OleksandR shows how inlined closures can be used to eliminate calls to MainEvaluate
. This is crucial for my application, since I need every last drop of performance mma can offer. Here is an extremely simplified working example (before you run this code, make sure to evaluate this package, containing the NelderMeadMinimize code):
Needs["CompiledFunctionTools`"]
With[{minimizer =
NelderMeadMinimize`Dump`CompiledNelderMead[
Function[{a, b, c}, (a - d1)^2 + (b - d2)^2 + (c - d3)^2], {a, b, c},
"ReturnValues" -> "OptimizedParameters"],
epsilon = $MachineEpsilon},
orgFitter =
Compile[{{d1, _Real, 0}, {d2, _Real, 0}, {d3, _Real, 0}},
minimizer[RandomReal[{0, 1}, {3 + 1, 3}], epsilon, -1],
CompilationOptions -> {"InlineCompiledFunctions" -> True},
RuntimeOptions -> {"Speed", "EvaluateSymbolically" -> False}]];
StringMatchQ[CompilePrint[orgFitter], "*MainEvaluate*"]
(* -> False *)
orgFitter[12, 2, 3]
Now, if I change (a - d1)^2 + (b - d2)^2 + (c - d3)^2
to calling a compiled function the calls to MainEvalute
are not eliminated! Please, instead of the simple myHi2
imagine a monster of a compiled procedure containing several hundred lines.
myHi2 = Compile[{{a, _Real, 0}, {b, _Real, 0}, {c, _Real,
0}, {d1, _Real, 0}, {d2, _Real, 0}, {d3, _Real,
0}}, (a - d1)^2 + (b - d2)^2 + (c - d3)^2];
With[{minimizer =
NelderMeadMinimize`Dump`CompiledNelderMead[
Function[{a, b, c}, myHi2[a, b, c, d1, d2, d3]], {a, b, c},
"ReturnValues" -> "OptimizedParameters"],
epsilon = $MachineEpsilon},
orgFitter =
Compile[{{d1, _Real, 0}, {d2, _Real, 0}, {d3, _Real, 0}},
minimizer[RandomReal[{0, 1}, {3 + 1, 3}], epsilon, -1],
CompilationOptions -> {"InlineCompiledFunctions" -> True,
"InlineExternalDefinitions" -> True},
RuntimeOptions -> {"Speed", "EvaluateSymbolically" -> False}]];
StringMatchQ[CompilePrint[orgFitter], "*MainEvaluate*"]
(* -> True *)
orgFitter[12., 2., 3.]
How can I eliminate this calls to MainEvaluate
?
Also, could someone help me understand, why this does not compile:
orgFitter = Compile[{{d1, _Real, 0}, {d2, _Real, 0}, {d3, _Real, 0}},
With[{minimizer =
NelderMeadMinimize`Dump`CompiledNelderMead[
Function[{a, b, c}, (a - d1)^2 + (b - d2)^2 + (c - d3)^2], {a,
b, c}, "ReturnValues" -> "OptimizedParameters"],
epsilon = $MachineEpsilon},
minimizer[RandomReal[{0, 1}, {3 + 1, 3}], epsilon, -1]],
CompilationOptions -> {"InlineCompiledFunctions" -> True,
"InlineExternalDefinitions" -> True},
RuntimeOptions -> {"Speed", "EvaluateSymbolically" -> False}];
CompilePrint[orgFitter]