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 forConstantArrayfor situation 2 and 3 ? - Why in 1, there is no error message, while in 2 and 3 there are error message?
Evaluatemust wrap the whole argument, it does not work buried inside a CompoundExpression. – Simon Woods Dec 31 '15 at 16:56Compile[{x,y}, Evaluate[Block[{a}, a=ConstantArray[x, {2,2}]; y; a}]]], withEvaluatesurrounding the whole expression, works. If you need to control evaluation, usingInlineExternalDefinitionsas you show is the way to go. No idea on the error messages. – ZachB Jan 01 '16 at 02:48Evaluateis documented, in Possible Issues section we can read: "Evaluateworks 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. – jkuczm Jan 01 '16 at 19:11deepEvaluateis extremely useful inCompile. Thanks so much for sharing. Would you like to make it an answer and add some explanation? – matheorem Jan 02 '16 at 06:23