システムイメージのビルド

システムイメージのビルド

Julia のシステムイメージをビルドする

Julia には、sys.ji という名前の、 Base モジュールの内容を含む事前解析済みのシステム イメージが付属しています。 このファイルは、起動時間を大幅に改善できるように、できるだけ多くのプラットフォーム上で、sys.{so,dll,dylib}という共有ライブラリにもプリコンパイルされます。 プリコンパイル済みシステムイメージファイル が Julia に付属されないようなシステムでであれば、Julia の DATAROOTDIR/julia/base フォルダーに同梱されているソース・ファイルからシステムイメージファイルを生成できます。

システムイメージの自前ビルドは、複数の理由で役立ちます。 ユーザーは以下を実行できます:

PackageCompiler.jl package には、このプロセスを自動化するための便利なラッパー関数が含まれています。

複数のマイクロアーキテクチャ向けに最適化されたシステムイメージ

システム イメージは、同じ命令セット アーキテクチャ (ISA) の下で複数の CPU マイクロアーキテクチャーに対して同時にコンパイルできます。異なる ISA 拡張機能やその他のマイクロアーキテクチャ機能を利用するために、共有関数には最小限のディスパッチポイントを挿入することで、複数バージョンの関数を作成できます。最高のパフォーマンスを提供するバージョンは、利用可能な CPU 機能に基づいて実行時に自動的に選択されます。

複数のシステム・イメージ・ターゲットを指定する

マルチマイクロアーキテクチャーのシステム・イメージは、システム・イメージのコンパイル中に複数のターゲットを渡すことによって使用することができます。複数ターゲットの指定は、JULIA_CPU_TARGET make オプションをつかってもできますし、コンパイルコマンドを手動で実行する場合は-C コマンドラインオプションを使用することもできます。 オプション文字列内で複数のターゲットは ; で区切ります。 各ターゲットの構文は、CPU 名の後に , で区切られた複数の機能を記します。 LLVM でサポートされているすべての機能がサポートされており、- プレフィックスを使用して機能を無効にすることができます。 (+ 接頭部も許可され、LLVM 構文と一致するように無視されます)。 さらに、関数の複製動作を制御するいくつかの特別な機能がサポートされています。

  1. clone_all

    デフォルトでは、マイクロアーキテクチャ機能から最も恩恵を受ける可能性が最も高い関数のみクローンされます。 ターゲットに clone_all が指定されている場合は、全ての 関数がターゲットに対して複製されます。 負形式 -clone_all を使用すると、全関数のクローンから、組み込みのヒューリスティック操作を抑制することができます。

  2. base(<n>)

    ここで、<n> は負でない数値のプレースホルダを示します (たとえば、base(0)base(1))など。 部分的に複製された(つまりcloneallではない)ターゲットで、ある関数が複数されていなければ、基本ターゲットの関数が使用されます。デフォルトで基本ターゲットは、0番 (最初に指定されたターゲット)です。base(<n>)オプションでn番目のターゲット (0 から始まる) を基本ターゲットとして指定することができます。 基本ターゲットに指定できるのは、0または別のターゲットの中でもcloneall`指定がされているものでなければいけません.。そうでないと、エラーが発生します。

  3. opt_size

    実行時間性能への影響が重大でない限りは、関数のサイズ最適化が行われます。 これはGCCやClang でいうところの -Os オプションに相当します。

  4. min_size

    実行時間性能に重大な影響があったとしても、強制的にサイズ最適化をします。 Clang オプションでいうところの -Oz に相当します。

例として示しますが、本ページ執筆時点で julialang.orgからダウンロード可能な公式のx86_64 Julia バイナリの作成には、次のオプション文字列が使用されています:

generic;sandybridge,-xsaveopt,clone_all;haswell,-rdrnd,base(1)

これにより、3 つの別個のターゲットを持つシステム イメージが作成されます。一つは、一般的な x86_64 プロセッサ、もう一つは sandybridge ISA (明示的に xsaveopt を除いています) を持つプロセッサで、すべての関数を明示的にクローン化するオプションを指定しました。最後は haswell ISA をターゲットにプロセッサで、 sandybridge sysimg バージョンに基づいており、rdrnd を除外しました。Julia 実装が生成された sysimg を読み込むと、ホスト プロセッサが CPU 機能フラグとの一致をチェックし、可能な限り最高の ISA レベルを有効にします。 基本レベル (generic) にはcx16 命令が必要です。 あるいは、互換性を高めるためにターゲット generic,-cx16 で sysimg を生成することもできますが、一部のコードではパフォーマンスと安定性の問題が発生する可能性があることに注意してください。

実装概要

これは、実装に関連するさまざまな部分の簡単な概要です。 実装の詳細については、各コンポーネントのコード コメントを参照してください。

  1. システムイメージのコンパイル

    解析とクローン作成の決定は src/processor* で行われます。 現在、サポートしているのは、ループ、simd命令、または他の数学演算(例えば、fastmath, fma、muladd)などの存在に基づく関数のclone 機能です。 この情報は、実際のクローン作成を行う src/llvm-multiversioning.cpp に渡されます。 この情報の受け渡しで、クローニングとディスパッチスロットの挿入に加えて (この方法については、MultiVersioning::runOnModuleのコメントを参照してください)、 メタデータの生成も行われるため、ランタイムは、システム イメージがロード・初期化することができます。 メタデータの詳細な説明は src/processor.h をみると分かります。

  2. システムイメージの読み込み

    システム イメージの読み込みと初期化はsrc/processor* で、システム イメージの生成中に保存されたメタデータで解析することで行われます。 ホスト機能の検出と選択の決定はsrc/processor_*.cpp で行われます。ファイルは、ISA によって異なります。 ターゲットの選択では、まずは、完全に一致する CPU 名、より大きいベクター レジスタサイズ、そしてより多いフィーチャーの数のものが優先されます。 このプロセスの概要はsrc/processor.cppにあります。