How to avoid "CopyTensor" in compile function with external call?

The CopyTensor is an artifact produced by inlining. Instead, you can try inlining with With as follows:

cf1 = Compile[{{h, _Complex, 1}},
   Table[0. I, {a, 1, 5, 1}, {b, 1, 5, 1}],
   CompilationTarget -> "C"
   ];
cf2 = With[{cf1 = cf1},
   Compile[{{h, _Complex, 1}},
    cf1[h],
    CompilationTarget -> "C"
    ]
   ];

Now the pseudo code reads as

CompiledFunctionTools`CompilePrint[cf2]

[...]

1 T(C2)1 = LibraryFunction[<>, compiledFunction11, {{Complex, 1, Constant}}, {Complex, 2}][ T(C1)0]]

2 Return

So we replaced the CopyTensor by a function call. Since in C, arrays are passed by reference, this should be faster than a CopyTensor. But I am not sure. One should try both variants and choose the one that performs better.

PS.: One can also try to set CompilationTarget -> "WVM" in both Compiles. Then the critical lines of code looks like this:

[...]

1 T(C2)1 = CompiledFunctionCall[ Hold[CompiledFunction[{h}, Table[0. I, {a, 1, 5, 1}, {b, 1, 5, 1}], -CompiledCode-]][ T(C1)0]]

2 Return

Sometimes, it is better to not leave the Wolfram Virtual Machine when frequently calling compiled functions by each other.


You could use simple quoting mechanism to inline code of one function into another at top level.

ClearAll[quote, inline, unquote, eval]
SetAttributes[{quote, unquote}, HoldAllComplete]
quote@expr : Except@_Symbol := Unevaluated@expr /. {x : _unquote | _quote | _inline :> x, s_Symbol :> quote@s}
unquote@args___ := args
eval = # /. HoldPattern@quote@s_ :> s &;

inline::unsupported = "`1` is not one of function formats supported by inline.";
inline@HoldPattern@Function@body_ := Function@quote@body
inline@HoldPattern@Function[args_ , body_, attrs_ | PatternSequence[]] := Function[args, quote@body, attrs]
inline@HoldPattern@CompiledFunction[___, f_Function, ___] := inline@f
inline@f_ := (Message[inline::unsupported, HoldForm@f]; $Failed)

Note that such inlining will not exactly mimic behavior of function call in top level Mathematica code. It'll fail if function result relies on argument evaluation, before they are passed to function body, or when single symbol used as function argument can represent Sequence of function arguments. In top level code, above inlining works, for arbitrary arguments, only when inlined function has HoldAllComplete attribute, but for compiled functions neither evaluation control nor Sequence splicing is relevant.

In case from OP:

cf1 = Compile[{{h, _Complex, 1}}, Module[{fab},
  fab = Table[0. I,{a,1,5,1},{b,1,5,1}];
  fab
]];

cf2 = quote@Compile[{{h, _Complex, 1}},
  Module[{fab}, fab = inline[cf1]@h]
] // eval;

Needs@"CompiledFunctionTools`"
CompilePrint@cf2
(* ...
1   I2 = I1
2   I3 = I1
3   I5 = I6
4   T(C2)1 = Table[ I2, I3]
5   I4 = I6
6   goto 11
7   I7 = I6
8   goto 10
9   Element[ T(C2)1, I5] = C0
10  if[ ++ I7 <= I3] goto 9
11  if[ ++ I4 <= I2] goto 7
12  Return *)

Tags:

Compile