Compileで使用するCコンパイラを変更する

Mathematica 8から、CompileでCコンパイラを使って直接ネイティブコードにコンパイルできるようになった。 使用するCコンパイラは、

Needs["CCompilerDriver`"];
CCompilerDriver`$CCompiler = {
   "Name" -> "GCC", 
   "Compiler" -> CCompilerDriver`GCCCompiler`GCCCompiler, 
   "CompilerInstallation" -> "/usr/bin",
   "CompilerName" -> Automatic
};

というように、CCompilerDriver`$CCompilerを変更して指定する。

以前からのCompile(“WVM”)と、各コンパイラの比較のため、ベンチマークを行ってみた。 検証環境は以下の通り。

  • CPU: Intel Core-i7 3770 (インテル® HT テクノロジー ON)
  • OS: Ubuntu 14.04 LTS 64bit
  • Memory: 16 GB DDR3 1333 MHz

検証するCコンパイラは、GCC、Intel C++ Compiler、Clangの3種類。

  • gcc: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
  • icc: icc (ICC) 14.0.3 20140422
  • clang: Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)

Mathematicaコードは以下。1/i^2を総和してπ^2/6を求める単純な計算を行った。 ※私の環境ではICCは/media/storage/intel/compserxe/binにインストールしているので下記コードを使用する場合は注意。

(* 従来のCompile *)
f1 = Compile[{{n, _Real}}, 
   Module[{a = 0.}, Do[a += 1./(i*i), {i, 1., n}]; Sqrt[6.*a]], 
   CompilationTarget -> "WVM", Parallelization -> True];

(* GCC *)
CCompilerDriver`$CCompiler =
   {"Name" -> "GCC", 
   "Compiler" -> CCompilerDriver`GCCCompiler`GCCCompiler, 
   "CompilerInstallation" -> "/usr/bin", 
   "CompilerName" -> Automatic};
f2 = Compile[{{n, _Real}}, 
   Module[{a = 0.}, Do[a += 1./(i*i), {i, 1., n}]; Sqrt[6.*a]], 
   CompilationTarget -> "C", Parallelization -> True];

(* ICC *)
CCompilerDriver`$CCompiler =
   {"Compiler" -> CCompilerDriver`IntelCompiler`IntelCompiler,
   "CompilerInstallation" -> 
   "/media/storage/intel/composerxe/bin"};
f3 = Compile[{{n, _Real}}, 
   Module[{a = 0.}, Do[a += 1./(i*i), {i, 1., n}]; Sqrt[6.*a]], 
   CompilationTarget -> "C", Parallelization -> True];

(* Clang *)
CCompilerDriver`$CCompiler =
   {"Name" -> "GCC", 
   "Compiler" -> CCompilerDriver`GCCCompiler`GCCCompiler, 
   "CompilerInstallation" -> "/usr/bin", "CompilerName" -> "clang"};
f4 = Compile[{{n, _Real}}, 
   Module[{a = 0.}, Do[a += 1./(i*i), {i, 1., n}]; Sqrt[6.*a]], 
   CompilationTarget -> "C", Parallelization -> True];

Timing[#[100000000.]] & /@ {f1, f2, f3, f4}

結果

コンパイラ 実行時間(s)
WVM 6.21569
GCC 0.956899
ICC 0.365287
Clang 0.364913

評判通りIntel C++ CompilerやClangはGCCよりも高速だった。 なお、呼び出す際のオーバーヘッドも計測してみたが、これはWVMでもネイティブコードでも変わらなかった。

結論としては、以下の通り。

  • Mathematica 8以上ではCompileのオプションCompilationTarget->“C”を指定して、ネイティブコードにコンパイルした方が数倍高速
  • Intel C++ CompilerとClangはともにGCCよりも3倍弱高速
  • 高速化したい場合は、Mathematicaに加えてCコンパイラもインストールしよう