Windows ML で ONNX モデルをコンパイルしてキャッシュする

コンパイルは、実行プロバイダー (EP) が実際に実行するハードウェア固有のバイナリに ONNX モデルを変換する手順です。 NPU と GPU では、大規模なモデルでは数秒から数分かかる場合があります。アプリが結果をキャッシュしない場合、ユーザーはアプリが起動するたびにそのコストを支払います。

このページでは、コンパイルに関連する内容、プリコンパイルするタイミング、キャッシュされたコンパイル済みモデルを再利用する前に検証する方法について説明します。

前提条件

コンパイル済みモデル互換性 API には、ML 2.3 以降Windows必要です。 アップストリーム ONNX ランタイムでは、 GetModelCompatibilityForEpDevices() はバージョン 1.23 で使用でき、 GetCompatibilityInfoFromModel() はバージョン 1.24 で使用できます。

2 種類のコンパイル

"コンパイル" は、2 つの異なる意味を持つことができます。 これらを分けることで、このページの残りの内容を理解しやすくなります。

  • グラフの最適化 — セッション作成時に ONNX Runtime が実行する Fusion、定数フォールディング、およびレイアウト作業。 これは安価で EP に依存せず、セッションを作成するたびに実行されます。
  • EP コンパイル — ONNX グラフを EP 独自の形式に変換し、その後、コンパイルをハードウェア固有のバイナリに変換します。 ハードウェア EP (QNN、OpenVINO、VitisAI、NvTensorRtRtx、MIGraphX) がこれを行うと、コストのかかる手順になります。 NPU では、大規模なモデルでは数十秒から数分かかる場合があります。

Windows ML では、ONNX ランタイムの EPContext メカニズムを使用して EP コンパイルの再支払いを回避できます。 最初のコンパイルでは、ハードウェア対応バイナリが *_ctx.onnx モデル (またはサイドカー .bin) にシリアル化されます。後のセッションでは、事前に構築されたバイナリが読み込まれ、変換が完全にスキップされます。

プリコンパイルする理由

Windows ML では、実行プロバイダーを使用する場合にプリコンパイルを強くお勧めします。 プリコンパイルにより、複数秒 (場合によってはマルチ分) のコールド スタートが 1 回限りのコストに変わり、アプリに次のことが提供されます。

  • 高速コールド スタート — その後の起動では、グラフ変換とハードウェア のコンパイルをスキップします。
  • 予測可能な動作 — プラットフォームでは、推論セッションを作成する前に、アプリが選択したデバイスに対してコンパイル済みモデルが最適かどうかを確認できます。
  • CPU とバッテリーの使用量が少 なくなります。起動時に同じグラフの再コンパイルを停止します。

プリコンパイルを行わないと、すべてのセッション作成で EP 変換とコンパイルがアプリで再実行され、ユーザーは毎回遅延を感じます。

プリコンパイルのタイミング

アプリがハードウェア EP をターゲットにするたびに事前コンパイルします。 次の 2 つのタイミング オプションを使用できます。

戦略 最適な用途 Trade-offs
Ahead-of-Time (AOT) — ビルド時またはインストール時にコンパイルし、コンパイルされた成果物を発送します。 管理されたハードウェア群とドライバー群、またはデバイスごとのインストーラー。 ビルドマシン上で実行できないターゲットには、クロスコンパイル用ツールが必要です。 ターゲット デバイスで成果物を検証し、再コンパイルフォールバックを提供します。
最初の実行時にコンパイルする (広範な配布に推奨) - コンパイルされた成果物を確認し、見つからない場合はコンパイルしてからキャッシュして再利用します。 多様なハードウェア環境全体にわたるストア アプリと一般消費者向け配布 ユーザーは、最初の起動時にコンパイル コストを 1 回支払います。

Windows ML チュートリアルでは、コンパイル済みの成果物が存在するかどうかを確認することで、コンパイル時の初回実行時の基本的なメカニズムを示します。 完全なキャッシュ管理の例ではありません。 アプリで既存のコンパイル済みモデルを再利用する前に、この記事で説明する互換性チェックを適用します。 コンテキストでのコンパイル API については、「モデルの コンパイル」を参照してください。

再利用する前にコンパイル済みモデルを検証する

コンパイル済みモデルは、EP およびそれを生成したデバイス構成に依存できます。 EP は、キャッシュされたモデルが一連のデバイスに対して互換性があり、最適であるかどうかを判断します。

コンパイル時に、EP は、コンパイル済みモデルのメタデータ プロパティに ONNX ランタイムが書き込む、NULL で終了する UTF-8 互換性文字列を生成できます。 文字列の形式と内容は EP によって定義されます。 アプリで解析や解釈を行ってはいけません。

アプリは、文字列とターゲット EP デバイスを GetModelCompatibilityForEpDevices()に渡します。 ONNX ランタイムは、EP ファクトリの検証実装を呼び出し、 OrtCompiledModelCompatibility 状態を返します。 ソース コントラクトについては、ONNX ランタイム リポジトリの GetModelCompatibilityForEpDevices() と ValidateCompiledModelCompatibilityInfo() を参照してください。

互換性チェックのシナリオ

同じ検証 API は、次の 2 つのシナリオで使用できます。

  • デバイスに既に存在するモデルを検証します。 GetCompatibilityInfoFromModel()を呼び出して、コンパイル済みのモデル ファイルから文字列を抽出します。 モデルが既にメモリ内にある場合は、 GetCompatibilityInfoFromModelBytes()を呼び出します。 次に、文字列を GetModelCompatibilityForEpDevices()に渡します。
  • コンパイル済みモデルをダウンロードする前に検証します。 非透過的な文字列を、コンパイル済みモデルと共に軽量メタデータとして発行します。 アプリは、最初に文字列を取得し、 GetModelCompatibilityForEpDevices()で検証し、返された状態がキャッシュまたはデプロイ ポリシーを満たす場合にのみ、大規模な可能性があるモデルをダウンロードできます。

リモート互換性メタデータと、それを生成した正確なコンパイル済み成果物のペアを維持します。 成果物が変更された場合は、関連付けられている互換性文字列を更新します。

どちらのシナリオでも、次の操作を行います。

  1. GetEpDevices()を呼び出して使用可能な EP デバイスを列挙し、推論セッションの構成に使用するのと同じ EP またはデバイス ポリシーを適用します。
  2. ローカル モデルまたはリモート モデルに関連付けられているメタデータから互換性文字列を取得します。
  3. 文字列と一致するデバイス グループを GetModelCompatibilityForEpDevices()に渡します。
  4. キャッシュまたはダウンロード ポリシーを返された状態に適用します。 Windows ML サンプルでは保守的なポリシーが使用され、コンパイル済みのモデルはEP_SUPPORTED_OPTIMALに対してのみ受け入れられます。

GetCompatibilityInfoFromModel() は、ディスクから完全な ONNX ModelProto を解析します。 モデル自体をダウンロードする前に互換性の決定を行う必要がある場合は、リモート メタデータ パターンを使用します。

API は、 OrtCompiledModelCompatibility 値を返します。

地位 Meaning 推奨されるアクション
EP_SUPPORTED_OPTIMAL コンパイル済みモデルはサポートされており、EP デバイスに最適です。 コンパイル済みモデルを再利用します。
EP_SUPPORTED_PREFER_RECOMPILATION コンパイル済みモデルはサポートされていますが、パフォーマンスを向上させるために再コンパイルすることをお勧めします。 モデルは実行できますが、最適なキャッシュ ポリシーによって再コンパイルされます。
EP_UNSUPPORTED コンパイル済みモデルは、現在の EP デバイスではサポートされていません。 コンパイル済みモデルを読み込まないでください。 元のモデルを再コンパイルするか、使用します。
EP_NOT_APPLICABLE EP は、提供されたデバイスの互換性の決定を提供しませんでした。 これは、EP が互換性検証を実装していない場合の既定値でもあります。 この状態は、キャッシュに互換性があることを示す証拠として扱わないようにしてください。 アプリに別の検証ポリシーがない限り、元のモデルを使用します。

最適のみのキャッシュ ポリシーでは、優先 EP の不足している互換性メタデータをキャッシュ ミスとして扱います。 互換性評価でエラーが返される場合は、その実行に元のモデルを使用します。アプリでは検証できないため、新しくコンパイルされた成果物を昇格させないでください。

新しいキャッシュ エントリを必要とする可能性があるイベントは次のとおりです。

  • 新しい EP がインストールされます。
  • GPU または NPU ドライバーが更新されます。
  • ユーザーのハードウェアの変更。
  • ソース ONNX モデルが変更されます。
  • アプリは、成果物の生成に使用される ONNX ランタイム、EP、またはコンパイル設定を変更します。

互換性 API は、EP デバイスに対して既存のコンパイル済み成果物を検証します。現在のソース モデルから成果物が生成されたかどうかは判断されません。 ソース モデルのバージョンまたはハッシュをキャッシュ キーに含め、コンパイル入力が変更されたときにキャッシュを無効にします。

アプリがさまざまなデバイスに分散されている場合は、コンパイル済みの成果物をローカル キャッシュの場所に格納して、各デバイスが独自のバイナリを生成して再利用できるようにします。

基本的な互換性チェック

次のヘルパー関数は、1 つの EP のコンパイル済みモデルをチェックします。 ヘルパーを呼び出す前に、推論セッションの構成に使用するのと同じ EP またはデバイス ポリシーを適用します。 デバイス コレクションは空でない必要があり、同じ EP のデバイスが含まれている必要があります。

static bool IsCompiledModelOptimal(
    OrtEnv ortEnv,
    string compiledModelPath,
    string epName,
    IReadOnlyList<OrtEpDevice> epDevices)
{
    string compatibilityInfo =
        ortEnv.GetCompatibilityInfoFromModel(compiledModelPath, epName);

    return !string.IsNullOrWhiteSpace(compatibilityInfo) &&
        ortEnv.GetModelCompatibilityForEpDevices(
            epDevices,
            compatibilityInfo) ==
        OrtCompiledModelCompatibility.EP_SUPPORTED_OPTIMAL;
}

セッションの作成前にチェックを使用します。

  • 結果がアプリの互換性ポリシーを満たしている場合は、コンパイル済みモデルを使用します。
  • それ以外の場合は、元のモデルを使用または再コンパイルします。

Windows ML サンプルは保守的なポリシーを使用し、EP_SUPPORTED_OPTIMALのみを受け入れます。 アプリによって、コンパイル済みモデルの格納、更新、置換の方法が決まります。

モデルのコンパイル

推論セッションで ONNX モデルを使用する前に、多くの場合、デバイスの基になるハードウェアで効率的に実行できる最適化された表現にコンパイルする必要があります。

ONNX Runtime 1.22 の時点で、コンパイル手順をより適切にカプセル化する新しい API があります。 詳細については、ONNX ランタイムのコンパイル ドキュメントを参照してください ( OrtCompileApi 構造体を参照)。

// Prepare compilation options
OrtModelCompilationOptions compileOptions = new(sessionOptions);
compileOptions.SetInputModelPath(modelPath);
compileOptions.SetOutputModelPath(compiledModelPath);

// Compile the model
compileOptions.CompileModel();

Note

コンパイルが完了するまでに数分かかる場合があります。 UI の応答性を維持するには、これをアプリケーションのバックグラウンド操作として行うか、モデルの準備中にユーザーに警告することを検討してください。

参照