3
$\begingroup$

I would like to build up a Mathematica package Pck which contains compiled functions. However when loading this library I obtain an error. When reduced to a minimal (non-)working example, the notebook Pck.nb defining my package contains

BeginPackage["Pck`"];

f2::usage = "f2";
f1::usage = "f1";
f::usage = "f";

Begin["Private`"];

f2 = Compile[{{x, _Real}},
   1
   , CompilationTarget -> "C"];

f1 = Compile[{{x, _Real}},
   f2[x]
   , CompilationTarget -> "C"];

f = Compile[{{x, _Real}},
    f1[x]
   , CompilationTarget -> "C"];

End[];
EndPackage[];

As you may note, the functions f, f1 and f2 are imbricated one into another. I can then save this notebook as a Wolfram Mathematica package Pck.m. The next step is to load this package in my test notebook using

 << "Pck.m";

However, I obtain systematically obtain an error of the form

CCompilerDriver`CreateLibrary::cmperr: Compile error:
/.../compiledFunction2.c:83:12: 
error: static declaration of 'F1' follows non-static declaration >>

Compile::nogen: A library could not be generated from the compiled function. >>

It seems that having imbricated compiled functions leads to this error message.

However, even with this error, I can still successfully evaluate f[1] within the test notebook. If I get rid of f2, so that f1 does not require to evaluate f2, this error disappears. Therefore, my conclusion is that the interweaving of the compiled function is responsible for this bug. (Even if I had the constraints {{f1[_],_Real}} and {{f2[_],_Real}} to the definitions of f and f1, the bug remains.)

How could I solve this issue ? (In fact, in my real package, I even have a third layer of interweaving f3...)

$\endgroup$
  • 5
    $\begingroup$ 1. It appears that Mathematica generates invalid C code, which I would consider a bug even if it were the result of incorrect input. I would report this to support. 2. By nesting functions like this you lose all benefits of compilation unless you use CompilationOptions -> {"InlineCompiledFunctions" -> True, "InlineExternalDefinitions" -> True}. Using these options will also avoid the problem you're seeing. $\endgroup$ – Szabolcs Feb 9 '15 at 18:48
  • $\begingroup$ @Szabolcs Thank you, indeed it appears I didn't know this compilation option, which seems to solve my problem both in this simple example and my real notebook (I even got a $1/3$ speed-up). Indeed, now all the previous errors messages are gone. However, surprisingly, in my real notebook, I still get a red bracket (usually synonym of some errors), but with absolutely no error messages displayed. (I guess I need to investigate this a bit more...) $\endgroup$ – jibe Feb 9 '15 at 19:25
  • $\begingroup$ @chris okay, done. $\endgroup$ – Szabolcs Feb 9 '15 at 19:53
7
$\begingroup$

It appears that Mathematica is generating invalid C code, which is worth reporting to support even if it turns out to be caused by unsupported input.

That said, nesting compiled functions like this usually leads to performance degradations because the nested function will trigger a callback to the main evaluation loop.

In[10]:= << CompiledFunctionTools`

In[11]:= CompilePrint[f1]

Out[11]= "
        1 argument
        2 Integer registers
        1 Real register
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

        R0 = A1
        Result = I1

1   I1 = MainEvaluate[ Hold[f2][ R0]]
2   Return
"

This can often be fixed using these options in Compile:

CompilationOptions -> {"InlineCompiledFunctions" -> True, "InlineExternalDefinitions" -> True}

Incidentally this will also fix the error you are seeing.

$\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.