First, we load some tools related to Compile
for analysis.
Needs["CompiledFunctionTools`"]
On["CompilerWarnings"];
SetSystemOptions["CompileOptions" -> "CompileReportExternal" -> True];
0
test0 = Compile[{x}, ConstantArray[x, {2, 2}]]
will not show message, but
test0 // CompilePrint
shows there is MainEvaluate
like this
T(R2)1 = MainEvaluate[ Hold[ConstantArray][ R0, T(I1)0]]
1
test1 = Compile[{x}, Evaluate@ConstantArray[x, {2, 2}]]
test1
actually successfully compiled ConstantArray
!! Because test1//CompilePrint
shows
T(R2)0 = {{R0, R0}, {R0, R0}}
This is understandable, according to the doc
You can use Compile[...,Evaluate[expr]] to specify that expr should be evaluated symbolically before compilation.
2
Now comes the strangest part
test2 = Compile[{x, y}, Evaluate@ConstantArray[x, {2, 2}]; y]
running this directly popup error message
Compile::noinfo: No information is available for compilation of Evaluate[ConstantArray[x,{2,2}]]. The compiler will use an external evaluation and make assumptions about the return type. >>
Compile::extscalar: Evaluate[ConstantArray[x,{2,2}]] cannot be compiled and will be evaluated externally. The result is assumed to be of type Void. >>
and test2//CompilePrint
shows
V17 = MainEvaluate[ Function[{x, y}, {{x, x}, {x, x}}][ R0, R1]]
This is different from test0
, but it is still a MainEvaluate
.
3
Let us see this
test3 = Compile[{x}, Block[{y}, y = Evaluate@ConstantArray[x, {2, 2}]]]
test3 // CompilePrint
also show error message and
1 T(R2)1 = MainEvaluate[ Hold[ConstantArray][ R0, T(I1)0]]
2 T(R2)2 = MainEvaluate[ Hold[Evaluate][ T(R2)1]]
4
Since test1
is full compiled, so we can inline it freely as follows
Compile[{x, y}, test1[x]; y,
CompilationOptions -> {"InlineExternalDefinitions" ->
True}] // CompilePrint
Compile[{x}, Block[{y}, y = test1[x]],
CompilationOptions -> {"InlineExternalDefinitions" ->
True}] // CompilePrint
The above two both are fully compiled. Free from MainEvaluate
.
This trick also works for IdentityMatrix
, DiagonalMatrix
Question:
- Why
Compile[...,Evaluate[expr]]
is not working forConstantArray
for situation 2 and 3 ? - Why in 1, there is no error message, while in 2 and 3 there are error message?
Evaluate
must wrap the whole argument, it does not work buried inside a CompoundExpression. $\endgroup$Compile[{x,y}, Evaluate[Block[{a}, a=ConstantArray[x, {2,2}]; y; a}]]]
, withEvaluate
surrounding the whole expression, works. If you need to control evaluation, usingInlineExternalDefinitions
as you show is the way to go. No idea on the error messages. $\endgroup$Evaluate
is documented, in Possible Issues section we can read: "Evaluate
works only on the first level, directly inside a held function". To overcome this, you can use something like following function:deepEvaluate = Function[, Unevaluated[#] /. HoldPattern[Evaluate][x_] :> RuleCondition[x], HoldFirst];
Compile[{x, y}, Evaluate@ConstantArray[x, {2, 2}]; y] // deepEvaluate
. $\endgroup$