0
$\begingroup$

Im trying to compile the following function:

n := 5

fc = Compile[{{l,_Integer,1}},
    a=1;b=1;
    Do[
        If[l[[i]]==1,
            a=a+2b; b=b+i,
            b=a+b;  a=a+i],
        {i,n}];
    b,
    RuntimeAttributes -> {Listable},
    Parallelization -> True]

fc[Tuples[{0,1},n]]

However this gives the following errors:

CompiledFunction::pext: Instruction 1 in CompiledFunction[{10,11.2,5852},{{_Integer,1}},{{2,1,0},{2,0,1}},{{0,{2,0,2}},<<1>>,{1,{<<1>>}}},<<1>>,{{46,Function[{l},a=1],2,1,0,6,0,17},{46,Function[{l},b=1],2,1,0,6,0,17},{46,Function[{l},n],2,1,0,3,0,2},{40,50,3,0,2,2,0,1},<<10>>,{4,3,1,-8},{46,Function[{l},b],2,1,0,2,0,1},{1}},Function[{l},a=1;b=1;Do[If[l[[i]]==1,a=Plus[<<2>>];b=Plus[<<2>>],b=Plus[<<2>>];a=Plus[<<2>>]],{i,n}];b,Listable],Evaluate] calls ordinary code that can be evaluated on only one thread at a time.

and

CompiledFunction::cflist: Nontensor object generated; proceeding with uncompiled evaluation.

Additionally, the result is often wrong and inconsistent. It works correctly when Parallelization is turned off. Am I doing something wrong here or is there just something wrong with my setup?

$\endgroup$

1 Answer 1

4
$\begingroup$

If you CompilePrint your compiled function, you'll see lots of calls to MainEvaluate:

Needs["CompiledFunctionTools`"]
CompilePrint[fc]
    1 argument
    1 Boolean register
    11 Integer registers
    1 Tensor register
    Underflow checking off
    Overflow checking off
    Integer overflow checking on
    RuntimeAttributes -> {Listable}

    T(I1)0 = A1
    I5 = 0
    I1 = 5
    I8 = 2
    I0 = 1
    Result = I2

 1    V17 = MainEvaluate[ Function[{l}, a = 1][ T(I1)0]]
 2    V17 = MainEvaluate[ Function[{l}, b = 1][ T(I1)0]]
 3    I4 = MainEvaluate[ Function[{l}, n][ T(I1)0]]
 4    I6 = I5
 5    goto 14
 6    I7 = Part[ T(I1)0, I6]
 7    B0 = I7 == I0
 8    if[ !B0] goto 12
 9    V17I6 = MainEvaluate[ Function[{l, iCompile$9}, Block[{i = iCompile$9}, {a = a + 2 b, i}]][ T(I1)0, I6]]
 10   V17I6 = MainEvaluate[ Function[{l, iCompile$10}, Block[{i = iCompile$10}, {b = b + i, i}]][ T(I1)0, I6]]
 11   goto 14
 12   V17I6 = MainEvaluate[ Function[{l, iCompile$11}, Block[{i = iCompile$11}, {b = a + b, i}]][ T(I1)0, I6]]
 13   V17I6 = MainEvaluate[ Function[{l, iCompile$12}, Block[{i = iCompile$12}, {a = a + i, i}]][ T(I1)0, I6]]
 14   if[ ++ I6 <= I4] goto 6
 15   I2 = MainEvaluate[ Function[{l}, b][ T(I1)0]]
 16   Return

To avoid these calls to MainEvaluate, you should modularize the variables a and b. Also, the global variable n needs to have a value. So:

Clear[fc]
fc[n_] := Compile[{{l,_Integer,1}},
    Module[{a=1, b=1},
        Do[
            If[l[[i]]==1,
                a = a + 2b; b = b + i,
                b = a + b; a = a + i
            ],
            {i,n}
        ];
        b
    ],
    RuntimeAttributes->{Listable},
    Parallelization->True
];

Now, fc[n] has no calls to MainEvaluate:

n := 5;
CompilePrint[fc[n]]
    1 argument
    1 Boolean register
    10 Integer registers
    1 Tensor register
    Underflow checking off
    Overflow checking off
    Integer overflow checking on
    RuntimeAttributes -> {Listable}

    T(I1)0 = A1
    I3 = 0
    I1 = 5
    I6 = 2
    I0 = 1
    Result = I4

1   I2 = I0
2   I4 = I0
3   I7 = I1
4   I5 = I3
5   goto 19
6   I8 = Part[ T(I1)0, I5]
7   B0 = I8 == I0
8   if[ !B0] goto 15
9   I8 = I6 * I4
10  I9 = I2 + I8
11  I2 = I9
12  I9 = I4 + I5
13  I4 = I9
14  goto 19
15  I9 = I2 + I4
16  I4 = I9
17  I9 = I2 + I5
18  I2 = I9
19  if[ ++ I5 <= I7] goto 6
20  Return

Check:

fc[n][Tuples[{0,1},n]]

{26, 20, 35, 17, 35, 24, 37, 16, 32, 24, 43, 19, 39, 26, 39, 16, 30, 23, 42, 19, 42, 28, 43, 17, 35, 26, 47, 20, 41, 27, 40, 16}

$\endgroup$
2
  • $\begingroup$ Thanks! I didn't know about CompilePrint, that's very useful. $\endgroup$ Commented Oct 31, 2019 at 15:55
  • $\begingroup$ I have a question related to this: what if I want to use custom compiled functions inside fc? I have the same error message which is apparently related to the calls to MainEvaluate when I call the custom functions. $\endgroup$
    – Matteo
    Commented Nov 9, 2022 at 19:27

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.