4
$\begingroup$

Consider I have a function, with one version that compiled to the virtual machine and one that compiled to C:

fcp1[C0_, {xmin_, xmax_}, {tmin_, tmax_, dt_}] :=
 Compile[{},
  Module[{xls, Nx, tls, Ct, cdiagT, cdiagh, dx},
   Nx = Length[C0];
   dx = N@(xmax - xmin)/(Nx - 1);
   tls = Range[tmin, tmax, dt] + dt/2.;
   cdiagT = -1./(2. dx^2);
   Do[
    cdiagh = cdiagT;
    , {t, tls}]]
  , CompilationOptions -> {"InlineExternalDefinitions" -> True, 
    "InlineCompiledFunctions" -> True}
  ]


fcp2[C0_, {xmin_, xmax_}, {tmin_, tmax_, dt_}] :=
 Compile[{},
  Module[{xls, Nx, tls, Ct, cdiagT, cdiagh, dx},
   Nx = Length[C0];
   dx = N@(xmax - xmin)/(Nx - 1);
   tls = Range[tmin, tmax, dt] + dt/2.;
   cdiagT = -1./(2. dx^2);
   Do[
    cdiagh = cdiagT;
    , {t, tls}]]
  , CompilationOptions -> {"InlineExternalDefinitions" -> True, 
    "InlineCompiledFunctions" -> True}, CompilationTarget -> "C"
  ]

Now if we compare their compilation speed (the time it take MMA to compile the function, not the time to execute the function), the C compilation is very slow:

Nxgrid = 2000;

Ct0 = Array[Exp[-5. #^2] &, Nxgrid, {-1., 1.}] // 
   Developer`ToPackedArray;

xRange = {-199.9`, 199.9`};

dt = 0.05515999116515042`;

Ntgrid = 20000;

Needs["CompiledFunctionTools`"]


CompilePrint@f1 == CompilePrint@f2
f1 = fcp1[Ct0, xRange, {0, dt*Ntgrid, dt}]; // AbsoluteTiming
f2 = fcp2[Ct0, xRange, {0, dt*Ntgrid, dt}]; // AbsoluteTiming

(*True*)
(* {0.000642, Null} *)
(* {14.959721, Null} *)

So why does the C compilation so much slower than the WVM version, and how to speed it up?

Update

MarcoB gave a good suggestion to look at the compilation time independent of Mathematica. So I tested the compilation:

The documentation says the CCompilerDriver will be automatically involked when compiling to C. And it indeed seems quite slow.

Needs["CCompilerDriver`"]    
file = Export[FileNameJoin[{$TemporaryDirectory, "fcp1.c"}], 
    f1]; // AbsoluteTiming
CreateObjectFile[{file}, "fcp1"]; // AbsoluteTiming
(* {0.505879, Null} *)
(* {7.194721, Null} *)

And the compiler CCompilerDriver involked is Clang in my system

DefaultCCompiler[]
(* CCompilerDriver`ClangCompiler`ClangCompiler *)

so I also tested it outside MMA:

Import["!clang -v 2>&1", "Text"]
Import["!clang -shared -o " <> 
    ToString@FileNameJoin[{$TemporaryDirectory, "fcp1.so"}] <> " " <> 
        ToString@FileNameJoin[{$TemporaryDirectory, "fcp1.c"}] <> " -I" <>
         ToString[
         FileNameJoin[{$InstallationDirectory, 
       "SystemFiles/IncludeFiles/C/"}]] <> " 2>&1", 
   "Text"]; // AbsoluteTiming

(* "Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0 Thread model: posix" *)

(* {0.750312, Null} *)


Import["!nm " <> ToString@FileNameJoin[{$TemporaryDirectory, "fcp1.so"}], "Text"]

".....
0000000000013140 T _fcp1
0000000000017030 b _funStructCompile
0000000000017020 d _initialize
                 U dyld_stub_binder"

It looks like compile outside of MMA is very fast. So:

  1. Why does CCompilerDriver take long time to compile?
  2. CCompilerDriver takes about 7s in the last example, so why Compile take about 15s?
$\endgroup$
14
  • $\begingroup$ Let me see if I understand your question: you are asking about the time it takes to compile the function, not to execute it once it has been compiled, correct? $\endgroup$
    – MarcoB
    Commented Jul 22, 2015 at 23:05
  • $\begingroup$ @MarcoB yes, that's correct. $\endgroup$ Commented Jul 22, 2015 at 23:09
  • 1
    $\begingroup$ On my machine, Windows 10 with Visual Studio 2015 C compiler, f2 takes about 2 seconds. So maybe a different compiler will help you here. $\endgroup$
    – RunnyKine
    Commented Jul 23, 2015 at 3:36
  • 2
    $\begingroup$ I don't really know why compilation is so comparatively slow. I think I have missed something though: how is this typically going to affect performance? Of course, you would not compile your function every time you evaluate it. That approach does not seem to have any great upsides, but it is likely to kill any advantage you get from the compilation in all but the most extreme of cases. $\endgroup$
    – MarcoB
    Commented Jul 23, 2015 at 3:51
  • 1
    $\begingroup$ With Windows 8.1 and Visual Studio 2013 I am also getting 2 sec for f2. I guess its machine specific compiler issue. $\endgroup$ Commented Jul 23, 2015 at 9:06

0

Your Answer

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

Browse other questions tagged or ask your own question.