11
$\begingroup$

Bug introduced in 9.0 and persisting through 11.0


Following code worked on Mathematica 8, but in Mathematica 9 it can't be compiled, it return this message

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

How can I fix this?

Clear[cf1];
cf1 = Compile[{},
   Module[{s = 0.0},
    Do[
      If[s > 15, Print@i; Break[]];
      s = s + 1.0/i;
      , {i, 10^7}];
    ], CompilationTarget -> "C"];

cf1[]
$\endgroup$
7
  • 3
    $\begingroup$ You function does not return anything and it uses a Print which is never a good idea inside a compiled function. Removing the Print fixed your problem here. $\endgroup$
    – halirutan
    Jun 2, 2013 at 18:23
  • 1
    $\begingroup$ Although I haven't tried it, I'm certain that @halirutan is correct so, probably, V9 is doing a better job of flagging uncompilable functions In addition, I'd point out that I don't see any output coming from your function. Perhaps, you should replace Do with Table and remove the semi-colon from the final statement inside the loop. $\endgroup$ Jun 2, 2013 at 18:31
  • 2
    $\begingroup$ Regardless of the fact that the use of Print is not optimal, this does seem to be a bug in the version 9 VM or CCodeGenerator` package. The same bytecode is generated by versions 8 and 9, but the interpretation of it by version 9 seems to be incorrect. It's not clear to me why this only shows up with CompilationTarget -> "C". $\endgroup$ Jun 2, 2013 at 18:52
  • 1
    $\begingroup$ @OleksandrR. But Print, so far as I know, is not compilable. It certainly doesn't appear in the list Compile`CompilerFunctions[] and CompilePrint[cf1] reveals a callback to MainEvaluate. $\endgroup$ Jun 2, 2013 at 19:48
  • 1
    $\begingroup$ @MarkMcClure that's correct, but irrelevant to the situation except in as much as it might expose a bug that would remain hidden otherwise (cf. this). The presence of a call back into the interpreter certainly should not trigger an exception that leads to re-evaluation of the entire function, and especially not in a version-specific way and only for a particular compilation target. I think the most likely situation is that version 9 produces an incorrect translation of the bytecode to C. $\endgroup$ Jun 2, 2013 at 20:11

1 Answer 1

16
$\begingroup$

In version 8, the callback into the interpreter (also known as MainEvaluate or WolframCompileLibrary_Functions->evaluateFunctionExpression) looks like

Function[{iCompile$1}, Block[{i = iCompile$1}, {Print[i], i}]][register]

where register is the (integer, scalar) register that contains the value of i. This looks correct to me, although I'll admit that I don't understand the reason for translating Print[i] into {Print[i], i}.

In version 9, however, it takes the incorrect form:

Function[{}, Print[i]][register]

Since this is obviously wrong (which one can also see from the fact that i is printed literally), the question might as well ask why it works at all, even without translating the bytecode to C. The reason is that the bytecode contains the instruction

{46, Function[{}, Print[i]], {i, 2, 0, 3, Block}, 6, 0, 17}

in both versions, and it is the responsibility of the execution host (either the VM, or the CCodeGenerator` package in case of translation to C) to interpret this into a valid call. Clearly, the VM is capable of doing this in both version 8 and version 9, which is not surprising since I don't believe that any changes were made to the VM in version 9. Thus, although this problem resembles the one discussed in this question, I don't think the bugs are actually related.

However, the CCodeGenerator` package was changed in version 9, and appears to have become broken in this respect. In conclusion: it's a bug--please report it.

Since bugs may not be fixed in a publicly available release for some time, you can work around the issue simply by removing the reference to Print and returning the value of i instead:

Clear[cf1];
cf1 = Compile[{},
   Module[{s = 0.0},
    Do[If[s > 15, Return[i]]; s = s + 1.0/i, {i, 10^7}]
   ], CompilationTarget -> "C"
  ];

cf1[]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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