For example, if we use some functions defined prior to Compile
, we usually have the main evaluators in the compiled codes, pointing to the definition of the function.
f[t_] := If[t <= 1., Cos[t]*Sin[t], 0.]
CompilePrint@
Compile[{{t, _Real}}, IdentityMatrix[2] - f[t],
CompilationOptions -> {"InlineCompiledFunctions" -> True,
"InlineExternalDefinitions" -> True}]
1 argument 1 Integer register 3 Real registers 2 Tensor registers Underflow checking off Overflow checking off Integer overflow checking on RuntimeAttributes -> {} R0 = A1 I0 = 2 Result = T(R2)1 1 T(I2)0 = MainEvaluate[ Hold[IdentityMatrix][ I0]] 2 R1 = MainEvaluate[ Hold[f][ R0]] 3 R2 = - R1 4 T(R2)1 = R2 + T(I2)0 5 Return
We can avoid main evaluator by using Evaluate
in the function, which specifically substidue the definition of the function. However, sometimes this introduces repeated code in the compiled results. For instance, in the following example, Evaluate
simplify expands a number into a matrix and repeatedly calculated this expression for two times. We can see that the 26-50 lines of the compiled code are essentially the same as 1-25 lines.
CompilePrint@
Compile[{{t, _Real}}, Evaluate[IdentityMatrix[2] - f[t + 1./2.]],
CompilationOptions -> {"InlineCompiledFunctions" -> True,
"InlineExternalDefinitions" -> True}]
1 argument 1 Boolean register 1 Integer register 12 Real registers 3 Tensor registers Underflow checking off Overflow checking off Integer overflow checking on RuntimeAttributes -> {} R0 = A1 I0 = 1 R3 = 1. R4 = 7. R1 = 0.5 R7 = 0. Result = T(R2)2 1 R2 = R1 + R0 2 B0 = R2 <= R3 (tol R4) 3 if[ !B0] goto 10 4 R2 = R1 + R0 5 R5 = Cos[ R2] 6 R6 = Sin[ R2] 7 R5 = R5 * R6 8 R6 = R5 9 goto 11 10 R6 = R7 11 R5 = - R6 12 R6 = I0 13 R6 = R6 + R5 14 R5 = R1 + R0 15 B0 = R5 <= R3 (tol R4) 16 if[ !B0] goto 23 17 R5 = R1 + R0 18 R8 = Cos[ R5] 19 R9 = Sin[ R5] 20 R8 = R8 * R9 21 R9 = R8 22 goto 24 23 R9 = R7 24 R8 = - R9 25 T(R1)0 ={ R6, R8 } 26 R6 = R1 + R0 27 B0 = R6 <= R3 (tol R4) 28 if[ !B0] goto 35 29 R6 = R1 + R0 30 R8 = Cos[ R6] 31 R9 = Sin[ R6] 32 R8 = R8 * R9 33 R9 = R8 34 goto 36 35 R9 = R7 36 R8 = - R9 37 R9 = R1 + R0 38 B0 = R9 <= R3 (tol R4) 39 if[ !B0] goto 46 40 R9 = R1 + R0 41 R10 = Cos[ R9] 42 R11 = Sin[ R9] 43 R10 = R10 * R11 44 R11 = R10 45 goto 47 46 R11 = R7 47 R10 = - R11 48 R11 = I0 49 R11 = R11 + R10 50 T(R1)1 ={ R8, R11 } 51 T(R2)2 ={ T(R1)0, T(R1)1 } 52 Return
So is there a way to fix this repeating?
Note that change only the argument of the external function, the behavior changes, why?
CompilePrint@
Compile[{{t, _Real}}, Evaluate[IdentityMatrix[2] - f[t]],
CompilationOptions -> {"InlineCompiledFunctions" -> True,
"InlineExternalDefinitions" -> True}]
1 argument 1 Boolean register 1 Integer register 6 Real registers 3 Tensor registers Underflow checking off Overflow checking off Integer overflow checking on RuntimeAttributes -> {} R0 = A1 I0 = 1 R1 = 1. R2 = 7. R5 = 0. Result = T(R2)2 1 B0 = R0 <= R1 (tol R2) 2 if[ !B0] goto 8 3 R3 = Cos[ R0] 4 R4 = Sin[ R0] 5 R3 = R3 * R4 6 R4 = R3 7 goto 9 8 R4 = R5 9 R3 = - R4 10 R4 = I0 11 R4 = R4 + R3 12 T(R1)0 ={ R4, R3 } 13 T(R1)1 ={ R3, R4 } 14 T(R2)2 ={ T(R1)0, T(R1)1 } 15 Return