2
$\begingroup$

Consider the data data0, data1:

data0 = RandomReal[{0, 1}, {10^4, 3}];
(*Number of columns pairs*)
npairs = 12;
data1 = RandomReal[{0, 1}, {100, 2*npairs}];

and some function func1 that would use the values of data0, data1:

func1[x1_, y1_, x2_, y2_, X0_, Y0_] = 
 Exp[-x1^2 - y1^2 - x2^2 - y2^2]/(X0^2 + Y0^2);

I would like to sum some boolean conditions using func1 for the following combinations of pairs of columns of data1:

PairCombinations={{1,2},{1,8},{2,12},{3,9},{4,5},{4,8}};

This is my code:

compblock2 = 
 Hold@Compile[{{data0, _Real, 1}, {data1, _Real, 
       2}, {PairCombinations, _Real, 2}}, 
     Module[{count, X0val, Y0val, xval1, yval1, xval2, yval2, Func1, 
       comb1, comb2}, count = 0.;
      X0val = Compile`GetElement[data0, 1];
      Y0val = Compile`GetElement[data0, 2];
      (*This Do goes over all pair combinations in the table PairCombination*)
      Do[
       (*These are the identifiers of the pairs of columns used in the calculation*)
       comb1 = PairCombinations[[m]][[1]];
       comb2 = PairCombinations[[m]][[2]];
       (*This Do goes over all rows of data1*)
       Do[
        (*Here I extract the values of the selected columns*)
        xval1 = Compile`GetElement[data1, i, 2*(comb1 - 1) + 1];
        yval1 = Compile`GetElement[data1, i, 2*(comb1 - 1) + 2];
        xval2 = Compile`GetElement[data1, i, 2*(comb2 - 1) + 1];
        yval2 = Compile`GetElement[data1, i, 2*(comb2 - 1) + 2];
        Func1 = func1[xval1, yval1, xval2, yval2, X0val, Y0val];
        (*This is the summation of boolean conditions*)
        count += Boole[Func1 > 0.001], {i, 1, Length[data1], 1}], {m, 
        1, Length[PairCombinations], 1}];
      {count}], CompilationTarget -> "C", RuntimeOptions -> "Speed", 
     RuntimeAttributes -> {Listable}, Parallelization -> True] /. 
   DownValues@func1 // ReleaseHold

When trying to compile the code, I get the error:

Compile::argcompten: The comparison, Greater, is invalid for tensor arguments.

This means that Func1 (and already xval1, etc.) is not the quantity of the desired type (scalar), but a tensor instead. I do not understand what is the origin of this problem.

How to fix this issue?

$\endgroup$

1 Answer 1

7
$\begingroup$

As often with Comiple, CompiledFunctionTools`CompilePrint is your friend: Since the function won't compile at all in its current state, I removed the problematic expression by trying count += Func1, and then I replaced count=0. with count={{0.}} to get rid of the error about tensor ranks in the addition. At this point, you can look at the compiled version of the function:

compblock2 = 
 Hold@Compile[{{data0, _Real, 1}, {data1, _Real, 
       2}, {PairCombinations, _Integer, 2}}, 
     Module[{count, X0val, Y0val, xval1, yval1, xval2, yval2, Func1, 
       comb1, comb2}, count = {{0.}};
      X0val = Compile`GetElement[data0, 1];
      Y0val = Compile`GetElement[data0, 2];
      (*This Do goes over all pair combinations in the table \
PairCombination*)
      Do[(*These are the identifiers of the pairs of columns used in \
the calculation*)comb1 = PairCombinations[[m]][[1]];
       comb2 = PairCombinations[[m]][[2]];
       (*This Do goes over all rows of data1*)
       Do[(*Here I extract the values of the selected columns*)
        xval1 = Compile`GetElement[data1, i, 2*(comb1 - 1) + 1];
        yval1 = Compile`GetElement[data1, i, 2*(comb1 - 1) + 2];
        xval2 = Compile`GetElement[data1, i, 2*(comb2 - 1) + 1];
        yval2 = Compile`GetElement[data1, i, 2*(comb2 - 1) + 2];
        Func1 = func1[xval1, yval1, xval2, yval2, X0val, Y0val];
        (*This is the summation of boolean conditions*)
        count += Func1, {i, 1, Length[data1], 1}], {m, 1, 
        Length[PairCombinations], 1}];
      {count}], CompilationTarget -> "C", RuntimeOptions -> "Speed", 
     RuntimeAttributes -> {Listable}, Parallelization -> True] /. 
   DownValues@func1 // ReleaseHold

<< CompiledFunctionTools`

CompilePrint@compblock2
(* "    3 arguments
        10 Integer registers
        7 Real registers
        15 Tensor registers
        Underflow checking off
        Overflow checking off
        Integer overflow checking off
        RuntimeAttributes -> {Listable}

        T(R1)0 = A1
        T(R2)1 = A2
        T(R2)2 = A3
        I4 = 0
        I1 = 2
        I9 = -1
        I0 = 1
        T(R2)3 = {{0.}}
        Result = T(R3)8

1   T(R2)9 = CopyTensor[ T(R2)3]]
2   R3 = GetElement[ T(R1)0, I0]
3   R2 = GetElement[ T(R1)0, I1]
4   I3 = Length[ T(R2)2]
5   I5 = I4
6   goto 84
7   T(R1)7 = Part[ T(R2)2, I5]
8   R1 = Part[ T(R1)7, I0]
9   T(R1)7 = Part[ T(R2)2, I5]
10  R0 = Part[ T(R1)7, I1]
11  I7 = Length[ T(R2)1]
12  I8 = I4
13  goto 83
14  R5 = I9
15  R4 = R1 + R5
16  R5 = I1
17  R5 = R5 * R4
18  R4 = I0
19  R5 = R5 + R4
20  R4 = I9
21  R6 = R1 + R4
22  R4 = I1
23  R4 = R4 * R6
24  R6 = I0
25  R4 = R4 + R6
26  T(R2)7 = MainEvaluate[ Hold[Compile`GetElement][ T(R2)1, I8, R4]]
27  R5 = I9
28  R4 = R1 + R5
29  R5 = I1
30  R5 = R5 * R4
31  R4 = I1
32  R5 = R5 + R4
33  R4 = I9
34  R6 = R1 + R4
35  R4 = I1
36  R4 = R4 * R6
37  R6 = I1
38  R4 = R4 + R6
39  T(R2)6 = MainEvaluate[ Hold[Compile`GetElement][ T(R2)1, I8, R4]]
40  R5 = I9
41  R4 = R0 + R5
42  R5 = I1
43  R5 = R5 * R4
44  R4 = I0
45  R5 = R5 + R4
46  R4 = I9
47  R6 = R0 + R4
48  R4 = I1
49  R4 = R4 * R6
50  R6 = I0
51  R4 = R4 + R6
52  T(R2)5 = MainEvaluate[ Hold[Compile`GetElement][ T(R2)1, I8, R4]]
53  R5 = I9
54  R4 = R0 + R5
55  R5 = I1
56  R5 = R5 * R4
57  R4 = I1
58  R5 = R5 + R4
59  R4 = I9
60  R6 = R0 + R4
61  R4 = I1
62  R4 = R4 * R6
63  R6 = I1
64  R4 = R4 + R6
65  T(R2)4 = MainEvaluate[ Hold[Compile`GetElement][ T(R2)1, I8, R4]]
66  T(R2)11 = Square[ T(R2)7]
67  T(R2)12 = - T(R2)11
68  T(R2)11 = Square[ T(R2)5]
69  T(R2)8 = - T(R2)11
70  T(R2)11 = Square[ T(R2)6]
71  T(R2)13 = - T(R2)11
72  T(R2)11 = Square[ T(R2)4]
73  T(R2)14 = - T(R2)11
74  T(R2)12 = T(R2)12 + T(R2)8 + T(R2)13 + T(R2)14
75  T(R2)8 = Exp[ T(R2)12]
76  R5 = Square[ R3]
77  R4 = Square[ R2]
78  R5 = R5 + R4
79  R4 = Reciprocal[ R5]
80  T(R2)12 = R4 * T(R2)8
81  T(R2)8 = T(R2)9 + T(R2)12
82  T(R2)9 = CopyTensor[ T(R2)8]]
83  if[ ++ I8 <= I7] goto 14
84  if[ ++ I5 <= I3] goto 7
85  T(R3)8 = {T(R2)9}
86  Return " *)

Immediately problematic is any line with MainEvaluate, because that is usually an indication that Compile didn't understand something as expected. Let's look at the first of them:

26  T(R2)7 = MainEvaluate[ Hold[Compile`GetElement][ T(R2)1, I8, R4]]

The T(Rx)y is to be read as "tensor of rank x, number y. Similarly, Ix is the xth integer register, and Ry the yth real register. So what is happening is that compile thinks you are doing something of the form

Compile`GetElement[{{...},...}, 123, 2.4]

which is obviously wrong. Tracking down where R4 comes from, you'll see that it ultimately comes from

7   T(R1)7 = Part[ T(R2)2, I5]
8   R1 = Part[ T(R1)7, I0]

which in turn come from

T(R2)2 = A3

This means that because A3 (the third argument) is declared as a rank 2 tensor of reals, Compile decided that your Compile`GetElement call gets a real number as index, making it invalid. Knowing this, the fix is easy: Simply replace {PairCombinations, _Real, 2} with {PairCombinations, _Integer, 2}:

compblock2 = 
 Hold@Compile[{{data0, _Real, 1}, {data1, _Real, 
       2}, {PairCombinations, _Integer, 2}}, 
     Module[{count, X0val, Y0val, xval1, yval1, xval2, yval2, Func1, 
       comb1, comb2}, count = 0.;
      X0val = Compile`GetElement[data0, 1];
      Y0val = Compile`GetElement[data0, 2];
      (*This Do goes over all pair combinations in the table \
PairCombination*)
      Do[(*These are the identifiers of the pairs of columns used in \
the calculation*)comb1 = PairCombinations[[m]][[1]];
       comb2 = PairCombinations[[m]][[2]];
       (*This Do goes over all rows of data1*)
       Do[(*Here I extract the values of the selected columns*)
        xval1 = Compile`GetElement[data1, i, 2*(comb1 - 1) + 1];
        yval1 = Compile`GetElement[data1, i, 2*(comb1 - 1) + 2];
        xval2 = Compile`GetElement[data1, i, 2*(comb2 - 1) + 1];
        yval2 = Compile`GetElement[data1, i, 2*(comb2 - 1) + 2];
        Func1 = func1[xval1, yval1, xval2, yval2, X0val, Y0val];
        (*This is the summation of boolean conditions*)
        count += Boole[Func1 > 0.001], {i, 1, Length[data1], 1}], {m, 
        1, Length[PairCombinations], 1}];
      {count}], CompilationTarget -> "C", RuntimeOptions -> "Speed", 
     RuntimeAttributes -> {Listable}, Parallelization -> True] /. 
   DownValues@func1 // ReleaseHold
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.