# How to avoid CopyTensor in CompiledFunctions?

In a reply here Leonid wrote, “Compile can handle a number of higher-level functions, such as Transpose, Partition, Map, MapThread, etc. Most of these functions return expressions, and even though these expressions are probably passed to the calling function, they must be created. For example, a call to ReplacePart which replaces a single part in a large array will necessarily lead to copying of that array. Thus, immutability generally implies creating copies.”

However, I still don't understand what things besides the obvious would lead to a CopyTensor. Please help me understand what constructs lead to CopyTensor in my CompiledFunction, and how the CopyTensor can be avoided.

-
I think every Set/ReplacePart of an element in a list would lead to CopyTensor. Maybe, CopyTensor is the safest way for Mathematica to avoid the memory allocation conflict. f = Compile[{}, Module[{x = {1, 2}}, x[[1]] = 2]]; CompilePrint[f]; 1 T(I1)1 = CopyTensor[ T(I1)0]] 2 Part[ T(I1)1, I0] = I1 3 Return –  DaoTRINH Feb 14 '14 at 17:32

I'm not sure this is the answer or not, but at least, if you don't like the CopyTensor, I have the solution here.

Problem: Create a compiled function to replace at position n with the value m in the list of {1,2..,10}.

f3 = Compile[{{n, _Integer}, {m, _Integer}},
Module[{x = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, x[[n]] = m; x]];
StringFreeQ[CompilePrint[f3], "CopyTensor"]

False


f3 uses CopyTensor to copy the old list to a new one and works on this new list.

f1 = Compile[{{n, _Integer}, {m, _Integer}},
Module[{x = Range[10]}, x[[n]] = m; x]];
f2 = Compile[{{n, _Integer}, {m, _Integer}},
Module[{x = Table[x, {x, Range[10]}]}, x[[n]] = m; x]];

StringFreeQ[CompilePrint[#], "CopyTensor"] & /@ {f1, f2}

{True, True}


By replacing the existing list with the commands that generates the same list (Range and Table), we don't have the CopyTensor, because the Compile has to generate the pseudo-code to generate this list, and use Part to replace at position n. So here, we trade off the CopyTensor by the generating list commands. Of course, there are no benefit of efficiency here, but CopyTensor disappears.

=========== EDIT ==============

I would like to add an simple example to illustrate how to avoid CopyTensor in a loop. When you have to insert or edit some elements in a long list, it is better to group the new value in one list and insert/add it to the old list at one time.

For example, I have a list of {1,2,3,4}, and I want to build a function that append to this list from {5,6,7...,n}. I have 2 approaches:

a) Use AppendTo in a Do loop. At each step of the Do loop, CopyTensor appears in a Do loop.

f1 = Compile[{{n, _Integer}},
Block[{x = {1, 2, 3, 4}}, Do[AppendTo[x, i], {i, 5, n}]; x]];

1   T(I1)3 = CopyTensor[ T(I1)0]]
2   I2 = I0
3   I4 = I3
4   goto 9
5   T(I1)1 ={ I5 }
6   T(I2)2 ={ T(I1)1 }
7   T(I1)4 = Insert[ T(I1)3, T(I0)4, T(I2)2]]
8   T(I1)3 = CopyTensor[ T(I1)4]]
9   if[ ++ I4 < I2] goto 5
10  Return


b) Use Range to generate a list of {5,6,7...,n}, then add to it to {1,2,3,4}. So CopyTensor also appears but just 2 times, not in a loop. This is the way to avoid CopyTensor in a Do loop, and of course it is effective.

f2 = Compile[{{n, _Integer}},
Block[{x = {1, 2, 3, 4}}, x = Join[x, Range[5, n]]]]

1   T(I1)2 = CopyTensor[ T(I1)0]]
2   I4 = I0
3   I7 = I5
4   I2 = Subtract[ I4, I6]
5   T(I1)1 = Table[ I2]
6   I8 = I6
7   goto 9
8   Element[ T(I1)1, I7] = I8
9   if[ ++ I8 < I4] goto 8
10  T(I1)3 = Join[ T(I1)2, T(I1)1]]
11  T(I1)2 = CopyTensor[ T(I1)3]]
12  Return


f1[100000]; // Timing
{17.362911, Null}

f2[100000]; // Timing
{0., Null}


17 seconds vs 0 second ! So not always CopyTensor is not efficient ! So in the case we can not avoid using CopyTensor, try to avoid putting CopyTensor in a loop. Calling CopyTensor few times is not really bad.

-
Trinh. Bạn có học tại trường Lương Thế Vinh, Đồng Nai không? –  minthao_2011 Feb 16 '14 at 14:28
Co chu. Thao lop Ly ah? Minh con hoc Nguyen Binh Khiem luon.. –  DaoTRINH Feb 16 '14 at 21:35
TRINH Tôi là giáo viên. Trường LTV sắp xây đó bạn. Cuối tháng Năm này là đập trường đó. Bạn học khoá bao nhiêu? Lớp chuyên gì? –  minthao_2011 Feb 16 '14 at 23:37
@ Dao Trinh. Năm sau kỉ niệm 20 năm thành lập trường. Một số cựu học sinh thành lập học bổng mang tên Lương Thế Vinh. Bạn vào trang wew của trường để biết thêm thông tin. Sẽ có lời ngỏ của thầy Trần Anh Dũng, Hiệu trưởng nhà trường. –  minthao_2011 Feb 17 '14 at 0:03