式のコンパイル
f[x_]:=x Sin[x]と定義したとする.右辺の式x Sin[x]は,
がどのような値をとっても適用可能な形で格納される.ユーザにより
の値が特定されると,値はx Sin[x]に代入され式の評価が行われる.特定される
の値は何でもよい.数値でも,リストでも,代数式であってもよい.Mathematica の内部コードはすべてのオブジェクト型に対応するように作られている.
しかし,すべてのオブジェクトに対応しなければいけないため,処理時間は余計にかかる.そこで,
が例えば,機械精度の数値であることがあらかじめ分かっているなら,多くの処理ステップを踏む必要がなくなるため,潜在的に,x Sin[x]のような式をもっと速く評価することが可能になる.
式で参照される変数がすべて数(もしくは論理変数)とみなせるなら,関数Compileを使うことで式を高速なコードにコンパイルすることができる.Compile[{x1, x2, ...}, expr]を使うと,式 expr はコンパイルされ,「コンパイル済み関数」を得ることができる.式を評価させるには,コンパイルされた関数に
を与えその関数を実行する.
Compileの結果としてコンパイル済み関数CompiledFunctionと呼ばれるオブジェクトが生成される.そこには,実際のコンパイル済み関数の評価に必要な命令コード(インストラクション)が入っている.インストラクションは,使用されるコンピュータの機械語で書かれているので,高速な計算処理を実現することができる.
| Compile[{x1,x2,...},expr] | を数値的な変数とし,式 expr を計算するコンパイル済み関数を生成する |
式のコンパイル

が何であっても,
x Sin[x]を計算することができる純関数を作り,それを

と呼ぶ.
| Out[1]= |  |
x Sin[x]を評価してコンパイルした関数を作る.
| Out[2]= |  |

も

も同じ答を出すが,引数が数値なら,

の方が計算が速い.
| Out[3]= |  |
数値を使う式や論理演算式を繰り返し評価する必要があるときは,Compileを使うと効率が上がる.関数Compileを一度呼び出すだけで,通常の Mathematica 式に比べ高速に処理してくれるコードが手に入る.
x Sin[x]のように,式が単純であればコンパイルしようがしまいが処理速度はあまり違わない.しかし,式が長くなると,最大で20倍程度まで処理速度を上げることができるため,コンパイルするメリットが大きい.
コンパイルして著しい違いが出るのは,単純な(数論的な)関数をたくさん使った式の場合である.複雑な計算,例えば,ベッセル関数(BesselK)や固有値の解析関数(Eigenvalues)を使った計算では,コンパイルしても処理速度はあまり向上しない.これは,計算時間の大半が,コンパイル処理に影響されない Mathematica 内部のアルゴリズムで費やされるからである.
ルジャンドル(Legendre)多項式の10次項を求めるコンパイル済み関数を作る.
Evaluateによって
Mathematica はコンパイルする前に多項式を明示的に構築する.
| Out[4]= |  |
引数を

としたときの10次の項を計算する.
| Out[5]= |  |
| Out[6]= |  |
数値的な関数であればコンパイルすることで計算速度を上げられる.しかし,それでも,できるだけ組込み関数を使うようにした方がよい.組込み関数は最適化してあるので,コンパイルされたユーザ定義の関数より速いことが多い.それに,引数の型が何であろうと同一関数で処理することができる.コンパイル済み関数だと,特定精度の数値的な引数にしか対応することができない.
また,組込み関数によっては自らが関数Compileを呼び出してコンパイルを行うものがある.例えば,数値積分の関数NIntegrateは,与えられた積分式を自動的にCompileを使う.同じように,プロット関数PlotとPlot3Dはプロットする式をあらかじめCompileできるようになっている.Compileを利用する組込み関数にはコンパイル指定のオプションCompiledが用意されている.Compiled->Falseとしておけば,式のCompileを禁止にする.
| Compile[{{x1,t1},{x2,t2},...},expr] | 変数 を型 の数とみなし,式 expr をコンパイルする |
| Compile[{{x1,t1,n1},{x2,t2,n2},...},expr] |
| 変数 を型 の数からなる 次元の配列とみなし,式 expr をコンパイルする |
| Compile[vars,expr,{{p1,pt1},...}] | 式の要素 を型 のオブジェクトとみなし,式 expr をコンパイルする |
| _Integer | 機械精度の整数型 |
| _Real | 機械精度の近似実数型 |
| _Complex | 機械精度の近似複素数型 |
| True|False | 論理変数 |
コンパイルで有効な変数の型
Compileの機能がうまく機能するには,式にある各オブジェクトの型が確定していることが不可欠である.特に指定がなければ,すべての変数は近似実数とみなされる.
別途指定さえすれば,変数が整数や複素数でも,真偽二値(TrueかFalse)の論理変数でも,さらに,数値配列的なものでもCompileをすることが可能である.変数の型を指定するにはパターンを使う.例えば,整数なら,
とパターンを指定する.また,論理値の型なら,TrueかFalseでなければならない論理変数を指定するためにTrue|Falseとパターンを指定する.
式

をコンパイルする.

と

は整数であると指定しておく.
| Out[7]= |  |
| Out[8]= |  |
整数型の行列についてリスト操作を行うための式をコンパイルする.
| Out[9]= |  |
生成したコンパイルコードを使いリスト操作を実行する.結果は整数で返される.
| Out[10]= |  |
Compileの扱える変数の型は,基本的に,コンピュータが機械語レベルで直接処理できる型なら何でもよい.つまり,機械精度の近似実数はCompileが使える.しかし,任意桁精度の実数はコンパイルできない.さらに,整数に関しては,機械精度の整数,例えば,
以内の整数にCompileを使うことができる.
コンパイルする式が四則演算や論理演算だけのものなら,Compileは入力される変数の型から演算の各ステップで生成される値はどの型のものか自動判定できる.しかし,他の関数を参照したりすると,Compileは返される値がどんな型のものか判断がつかなくなってしまう.そのようなときは,Compileは特に指定がなければ,戻り値はすべて近似実数の型とみなす.ただし,特別にリストで型のパターンを与えておけば,式を任意の型のものとして解釈させることも可能である.

の式をコンパイルする.パターン

にマッチするものは整数であると指定しておく.
| Out[12]= |  |
| Out[13]= |  |
Compileとは,引数の型に応じて最適化された関数を生成することにある.実は,Compileは,それが生成する関数がどんな型の引数を取ろうが正常に機能するようになっている.引数が最適化の対象以外の型なら,コンパイルした式ではなく,標準形の式が呼び出され,引数の型に応じた計算が行えるようになっている.
変数の平方根を計算するコンパイル済み関数を作っておく.
| Out[14]= |  |
| Out[15]= |  |
| Out[16]= |  |
Compileが的確にコンパイルするためには,与える引数の型だけでなく,実行時に生じるオブジェクトすべてについて型が判明していなければならない.オブジェクトによっては,型が実行時の引数の型に依存し特定できない.例えば,Sqrt[x]として平方根を計算すると,x が正の値ならば,実数 x に対する平方根は実数になる.しかし,x が負の値のときは複素数になってしまう.
Compileは常に同じ型の値を返さなければいけない.もし,Compileにより生成されたコードを実行して,実際に返ってくる型が前提とした型と違うときは,このコードによる計算は無効にされ,代りに標準式による計算が行われる.
この場合,最適化したコードは使われない.もとの標準式が使われる.
| Out[17]= |  |
Compileの重要な機能のひとつに,数学的な式だけでなくプログラム的なものもコンパイルすることができる点が挙げられる.例えば,Compileは条件式や制御フローの構造体も扱うことができる.
コンパイルするものが何であれ,コンパイル関数Compile[vars, expr]に与えた引数は評価されることなくコンパイル処理に直接回される.したがって,式の代りにプログラムもコンパイルすることができる.
ニュートン近似法に基づいた平方根の計算プログラムをコンパイルする.
| Out[18]= |  |
| Out[19]= |  |