NVIDIA Dynamo、LLM エンジン障害時の高速回復機能をプレビュー
本文の状態
日本語全文を表示中
詳細モードで約21分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
NVIDIA Developer Blog
NVIDIA は Dynamo のプレビュー機能として Shadow Engine Recovery を発表し、LLM エンジンの障害発生時に冷間起動を必要とせず、数秒で復旧する仕組みを導入した。
AI深層分析を開く2026年8月26日 06:58
AI深層分析
キーポイント
Shadow Engine Recovery の仕組み
NVIDIA Dynamo は、アクティブなエンジンと同じ GPU に完全に初期化されたシャドウエンジンを常時待機させ、GPU Memory Service を経由して重みを共有することで、障害発生時に数秒で切り替えを可能にする。
パフォーマンスの劇的改善
GLM-5.2 デプロイメントでのテストでは、従来の冷間起動による 283 秒のダウンタイムに対し、シャドウエンジン採用により 7.3 秒で復旧し、約 39 倍の速度向上を実現した。
バックグラウンドでの再初期化
障害発生後のシャドウエンジンの再初期化は、サービス提供経路(serving path)から完全に外れた背景で実行されるため、稼働中のトラフィックへの影響を最小限に抑える。
シャドウエンジンによる高速復旧
シャドウエンジンを使用することで、LLM推論の復旧時間を従来のコールドスタートである283秒から7.3秒に短縮できる。
重みのライフサイクルの分離
GPU メモリサービスにより、重みの寿命をエンジンプロセスから切り離し、プロセス終了後も GPU メモリ上に保持可能にする。
重要な引用
Shadow engine recovery, available as a preview feature in NVIDIA Dynamo, moves most of this recovery work off the serving path.
With shadow engine recovery, a second worker resumed serving in 7.3 seconds, nearly 39 times faster, minimizing disruption to service quality.
Bar chart comparing recovery time: 283 seconds for a cold restart, 7.3 seconds with a shadow engine.
Shadow engine recovery addresses each problem with a targeted optimization: decoupling weight lifetime from the engine process, and completing non-transferable initialization before a failure.
編集コメントを表示
編集コメント
LLM の可用性を高める技術として、シャドウエンジンによる即時フェイルオーバーは実用的な価値が高い。プレビュー段階ではあるが、大規模モデル運用の信頼性向上に寄与する重要な進展である。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
LLM エンジンプロセスが失敗した場合、従来の復旧手順はコールドスタート(完全再起動)です。これにはストレージから HBM へ重みを読み込み、カーネルをコンパイルし、NVIDIA CUDA グラフを取得する必要があります。大規模モデルの場合、初期化に数分かかることもあり、その間、生存しているワーカーが転送されたトラフィックをすべて引き受けることになります。
NVIDIA Dynamo でプレビュー機能として提供されている Shadow Engine Recovery(シャドウエンジン復旧)は、この復旧作業の大部分をサービングパスから外すことで実現します。アクティブなエンジンと同じ GPU 上に、完全に初期化済みのシャドウエンジンをアイドル状態で維持します。GPU Memory Service (GMS) が既存の重みを両方のエンジン間で共有するため、HBM 内に別のコピーを作成する必要はありません。アクティブプロセスが失敗した場合、シャドウエンジンが数秒で引き継ぎます。再初期化は完全にバックグラウンドで行われ、サービングパスには影響しません。
私たちは、2 ワーカー構成の GLM-5.2 デプロイメントにおいて意図的に 1 つのワーカーを停止させることで、この仕組みの影響を実測しました。シャドウエンジン復旧を使用しない場合、残りの 1 ワーカーが 283 秒間のコールドスタート中にすべての着信トラフィックを処理し、TTFT(Time to First Token)が増加し、障害期間中、ユーザーあたりのデコードレートも低下しました。一方、シャドウエンジン復旧を利用した場合、2 つ目のワーカーはわずか 7.3 秒でサービングを再開し、従来比約 39 倍の高速化を実現し、サービス品質への影響を最小限に抑えました。

Figure 1. 2 つのワーカーのうち 1 つが障害を起こした後に、もう 1 つのワーカーがサービス再開までにかかる時間。コールドスタートでは重みの読み込み、KV キャッシュのサイズ調整、オートチューニング、CUDA グラフの再取得が必要となるため時間がかかります。一方、事前に初期化されたシャドウエンジンを使えば、はるかに早くサービスを再開できます。
LLM 推論の回復が遅い理由:2 つのコアな問題
本番環境で使われる LLM エンジンは、プロセスのクラッシュや回復可能な CUDA エラー、一時的な集合通信障害など、復旧可能なソフトウェア障害に頻繁に見舞われます。こうしたケースでは、ハードウェアやドライバ、ノード自体は正常に動作しています。問題を起こしているのは、破損した状態を保持していたプロセスだけであり、同じ GPU 上で新しいエンジンプロセスを起動すれば通常は復旧できます。
なぜその新しいエンジンが初期化コストをスキップできないのか。そこには 2 つの根本的な障壁があります。
- 重み(Weights)はエンジンプロセスに紐付いている。GPU メモリはエンジンの CUDA コンテキストとリンクされており、そのコンテキスト自体もエンジンプロセスに依存しています。プロセスが終了すると、ドライバは GPU メモリ内に既に存在する重みを含むすべてのリソースを解放します。そのため、置き換えられた新しいエンジンプロセスは、重みの読み込み手順を最初から繰り返さなければなりません。
- 一部の初期化状態は転送できない。NCCL や
torch.distributedのコミュニケーターは特定の稼働中のプロセスにバインドされており、CUDA グラフもキャプチャ時に存在する仮想アドレスに固定されています。これらの状態は前のエンジンから受け継ぐことができないため、再起動のたびに再作成する必要があります。
シャドウエンジン回復は、各課題に対して標的を絞った最適化で対応します。具体的には、重みの寿命とエンジンのプロセスを分離し、障害発生時に転送不可能な初期化処理を完了させることです。
シャドウエンジン回復の仕組み
シャドウエンジン回復は、永続的な GPU メモリ、予備ウォームアップ済みのスタンバイエンジン、ワーカーレベルでの調整を組み合わせており、コールドスタートなしで迅速に回復を実現します。
GPU メモリサービス:LLM 推論のための永続的 GPU メモリ
GPU メモリサービス(GMS)は、重みなどの特定のメモリ領域を、エンジンプロセスとは独立して管理します。これらの領域をエンジンとは異なるプロセスが所有することで、エンジンを再起動しても重みがメモリ上に残存し続けます。その結果、同じ GPU 上の新しいエンジンも既存のメモリに接続することが可能になります。
GMS は、推論エンジンの代わりに各 GPU 上で物理的な GPU メモリを管理するサイドカーです。通常は待機状態であり、独自の CUDA コンテキストを持ちません。物理ページを割り当て、それらのハンドルを出力し、どのエンジンがいつ読み書きできるかを調整します。エンジンは接続してハンドルをインポートし、自身の CUDA コンテキスト内の仮想アドレスで基盤となるページをマップします。このマッピングは起動時に一度だけ行われ、その後のアクセスには GMS は関与しません。
この機能は、CUDA Virtual Memory Management API を基盤として構築されています。この API により、物理的な GPU メモリとそれに対応する仮想アドレスの寿命を独立して管理することが可能になります。
物理的な割り当て領域は参照カウントで管理されているため、いずれかのプロセスがマッピングを維持している限り、そのデータは保持されます。2 つのエンジンが同じ重みテンソルにマップする場合、両者は同じ物理バイトを共有し、それぞれがコンテキスト内のローカルな仮想アドレスを使用します。
重みを参照するカーネルは、通常のポインタを通じてアクセスしますが、これは重みが本来存在していた HBM(High Bandwidth Memory)への参照となるため、GMS(Global Memory Service)経由での読み込みであっても、エンジン独自で割り当てた場合と比べてコストの増大はありません。

このアーキテクチャには、主に 2 つの利点があります。
第一に、重みはエンジンの故障後も保持されます。カーネルが失敗したエンジンの CUDA コンテキストを削除しても、GMS の参照により物理ページはメモリ上に残存し続けます。これにより、新しいエンジンが即座にその領域をマッピングして再利用することが可能になります。
第二に、重みは並行実行中の複数のエンジン間で共有できます。そのため、同じ GPU 上で動作するセカンダリエンジンであっても、重みに関する追加のコスト(マーギナルコスト)は一切発生しません。
GMS を推論フレームワークに統合するには、ごく限られた変更だけで済みます。vLLM、SGLLang、NVIDIA TensorRT-LLM はいずれも、ウェイト用メモリプールにバインドされたカスタム `torch.cuda.CUDAPluggableAllocator` を通じて GMS を統合しています。エンジン内部では、ウェイトは通常の torch.Tensor として扱われます。GMS の導入は、起動時にフラグを切り替えるだけという簡便さです。
GMS はウェイトに限定されません。現在のプレビュー版では KV キャッシュへの GMS 利用には対応していませんが、この機能の開発は活発に進められています。将来的な目標は、プロモートされたシャドウエンジンがトラフィックの流入に合わせてキャッシュを再構築するのではなく、移行元のエンジンのキャッシュをマッピングできるようにすることです。
シャドウエンジン:ゼロコストで事前初期化された待機インスタンス
シャドウエンジンとは、アクティブなエンジンと同じ GPU 上に共存し、アイドル状態にある完全に初期化済みのエンジンプロセスのことです。ウェイトの共有によりこの構成が可能になっています。もしウェイトを共有しなければ、2 つ目のエンジンにはもう一つの完全なウェイトコピーが必要となり、リクエスト処理に利用可能なメモリが大幅に減少してしまいます。
シャドウエンジン(Shadow Engine)は、アクティブなエンジンと同じ起動パスを共有します。各 GPU 上でローカル GMS に接続し、重みマッピングを読み込み、ワーカー間の KV 転送に NCCL と NIXL を用いて通信経路を確立します。さらに CUDA グラフのキャプチャと必要なウォームアップ処理を実行し、起動完了時には即座にサービス提供可能な状態になります。
その後、シャドウはサービス提供ではなく「待機(パarked)」モードに入ります。メモリ内の使用可能な領域を解放し、自身の番が来るまでブロックして待ちます。
シャドウが待機前に事前に計算・準備しているものは以下の通りです:
- CUDA コンテキスト、キャプチャ済みグラフ、通信経路。これらは他のプロセスから継承できないため、シャドウエンジンが起動した際に即座に使用可能になります。
- 重みマッピング。GMS のハンドリングは既に完了しているため、シャドウを唤醒する際には初期化時に確保された仮想アドレスへの再マッピングだけで済みます。
シャドウが待機中に先送り(Deferred)しているのは以下の通りです:
- KV キャッシュの物理的割り当て。KV キャッシュはエンジンが保持する最大の再利用可能なアロケーションです。シャドウは待機中はアドレス範囲のみを予約し、物理的なバックアップを持たず、プロモーションされた際に初めてキャッシュを実体化します。
つまり、待機中のシャドウが保持するのは CUDA コンテキスト、キャプチャ済みグラフ、通信経路、重みマッピングのみで、重みの別コピーや KV キャッシュは不要です。この軽量なフットプリントにより、シャドウはアクティブなエンジンと同じデバイス上に共存でき、数秒以内での回復を可能にします。
ワーカー:単一のデプロイ可能なユニット
次の図は、これらのコンポーネントが各ワーカー内でどのように配置され、共有ルーターの背後でどのようにスケールするかを示しています。

図 3: 単一のルーターに接続されたワーカー群。2 エンジン構成は各ワーカー内部の仕組みであるため、ルーター、フロントエンド、オーケストレーターに変更を加えることなく恩恵を受けることができます。
これらの基盤機能は 1 つのポッドに統合されています。ワーカーには 2 つのエンジンコンテナに加え、GPU メモリへのアクセスを仲介する GMS サイドカーと、アクティブなエンジンを選出するための共有ロックが用意されています。
定常状態では、一方のエンジンがロックを保持して目覚め、GMS に接続され、展開済みの KV キャッシュを保持し、フロントエンドルーターに登録されます。もう一方は完全に初期化され GMS には接続されていますが待機状態で、KV キャッシュを持たず、ロックの解放を待ちます。
回復の詳細
以下のセクションでは、回復シーケンスを追跡し、信頼性を支える同期とメモリ管理の仕組みについて解説します。
シーケンス
ワーカーは定常状態に戻るまでに 4 つのフェーズを経ます。

図 4: 回復の 4 つのフェーズ。アクティブとシャドウの役割はエンジン A と B の間で入れ替わり、どちらのエンジンもウェイトを再読み込みすることなくワーカーは定常状態に戻ります。
・T₀ 定常状態。エンジン A がロックを保持し、起動してルーターに登録済みです。エンジン B は待機状態で、ロックの取得をブロックされています。
・T₁ 障害発生。エンジン A のプロセスが終了します。これはクラッシュしたか、あるいはライブネスプローブによってハングアップと判定され強制終了されたかのいずれかです。いずれにせよ、プロセスが回収される際にカーネルがロックを解放します。シャドウが登録するまでの間、ワーカーは一時的にルーティング不能となります。
・T₂ 切り替え。エンジン B がロックを取得し、起動して GMS を介して重みを再マッピングします。さらに KV キャッシュを初期化し、ルーターへ再登録を行います。一方、エンジン A のコンテナはオーケストレーターによって再起動されます。
・T₃ 再起動完了。エンジン A は初期化を終了し、シャドウ状態へと移行します。これで役割が入れ替わった定常状態となります。
シャドウの利点は、T₂に到達する時点で既に初期化されていることです。クリティカルパス上で実行すべき作業は、ロックの取得、重みの再マッピング、そして KV キャッシュの実体化のみです。
同期
ワーカーは、同時に起動できるエンジンが一つだけであることを保証する排他制御と、アクティブなエンジンに障害が発生した際にスタンバイエンジンが引き継ぐための信頼性の高い解放機能の両方を必要とします。共有ファイルに対する POSIX flock がこれらの保証を提供します。シャットダウン、セグフォールト、または SIGKILL によってアクティブなプロセスが終了すると、カーネルがそのファイル記述子を回収し、シャドウエンジンがロックを取得してサービス提供を開始します。
したがって、各エンジンの起動パスは短いリーダー選挙となります。
await engine.initialize() # weight load, torch.compile, autotune, CUDA graph capture
...
ロックの取得を待っている間は、エンジンをスリープ状態にします。
await engine.sleep()次に、フェイルオーバー用のロックオブジェクトを作成します。
lock = FlockFailoverLock(lock_path)
``` (原文の技術表記: `# put the engine to sleep while we wait on the lock`、`await engine.sleep()`、`lock = FlockFailoverLock(lock_path)`)
ロックを取得するまで待機します。
```python
await lock.acquire(engine_id=engine.id) # wait on the lock to wakeその後、エンジンを起動します。
await engine.wake()
``` (原文の技術表記: `await lock.acquire(engine_id=engine.id) # wait on the lock to wake`、`await engine.wake()`)
プロセスは生存しているにもかかわらずデッドロック状態に陥ったエンジンが、Kubernetes のライブネスプローブによって検出されると、連鎖的に `SIGKILL` が発令され、カーネル管理によるリリーストリガーが作動します。
## メモリ集計
1 つの GPU に 2 つのエンジンプロセスを収容し、HBM を枯渇させずに運用するには、ライフサイクル全体を通じて慎重なメモリ管理が求められます。

*Figure 5. GPU memory across a recovery*
- **重み(Weights)**:GMS によって一度割り当てられ、ワーカー内のすべてのエンジンで読み取り専用としてマッピングされます。重複して複製されることはありません。
- **KV キャッシュ**:現在アクティブなエンジンのみが保持します。起動時に実体化され、停止時に解放され、その領域はシャドウエンジンが引き継ぐために確保されます。
- **バッファとグラフ**:NCCL バッファ、CUDA コンテキスト、およびキャプチャされたグラフです。各エンジンは待機状態であってもこれらを保持しており、これは駐車中のシャドウの維持コスト全体を構成します。
## **ベンチマーク結果:GLM-5.2 におけるシャドウエンジン回復とコールドリスタートの比較**
その恩恵を定量化するため、2 ワーカー構成のファーム内でエンジン障害が発生した際のシャドウエンジン回復と、コールドリスタートを比較しました。
## **設定**
NVIDIA B200 ノード上で NVFP4 量子化された GLM-5.2 をサービングするワーカーを 2 つ実行しました。ノードごとに 1 ワーカーずつ配置し、TP=8、最大コンテキスト長は 200K、KV キャッシュには FP8 を使用しています。フロントエンドは単一で、リクエストをラウンドロビン方式で 2 つのワーカーに分散します。
負荷は合成データです。1 リクエストあたり入力トークンが 32,000、出力トークンが 1,000 で、到着頻度は秒間 0.7 リクエストです。
両方のワーカーは同一のエンジンビルドと設定を使用しています。唯一の違いはシャドウエンジンの有無です。ベースラインではシャドウエンジンをオフにしており、停止したワーカーはコールドスタートから再起動します。一方、Shadow Engine Recovery 構成では、各ワーカー・ポッドに事前初期化されたシャドウエンジンがホストされており、アクティブなエンジンが失敗した場合に引き継ぎが可能です。
障害注入は、ワークロードが定常状態に達した後に実施しました。2 つあるワーカーの 1 つに対して SIGKILL を発行し、その後 600 秒間にわたって観測を行いました。フリート内に 2 つのワーカーがある場合、1 つを失っても残りのワーカーはパートナーが復帰するまですべてのリクエストを引き受けます。
## **結果**

*Figure 6. Time to first token, 60-second rolling median. The baseline climbs for the whole 283 seconds its second worker is missing, crossing the 5-second line about 90 seconds in. With shadow engine recovery, p50 TTFT is more resilient to disruption*
図 6. 初回トークンまでの時間(TTFT)の 60 秒ローリング中央値。ベースラインでは、2 つ目のワーカーが欠落している間中 283 秒にわたり上昇し続け、約 90 秒で 5 秒の閾値を突破します。シャドウエンジン回復機能を使用すれば、p50 TTFT は障害に対してより耐性を持ちます。

図 7. トークン間レイテンシ(60 秒移動平均)。ベースラインは 84 ミリ秒に達するとその値を維持し、283 秒間にわたってほぼ横ばいを続けます。これは 50 ミリ秒の閾値を大きく上回る水準です。シャドウアームは障害発生時に一時的に上昇しますが、その後すぐに安定した状態に戻ります。
| **メトリック** | **ベースライン:コールドリスタート** | **シャドウエンジン回復** |
| --- | --- | --- |
| 2 番目のワーカーが再度サービスを提供するまでの時間 | 283 s | 7.3 s |
| 障害発生後の TTFT p50 | 23,815 ms | 1,311 ms |
| 障害発生後のデコードレート p50 | 12 tok/s/user | 46 tok/s/user |
| 最初のトークンまでの 5 秒以内の要求数 | 399 のうち 201 | 398 のうち 1 |
| ユーザーあたり 20 tok/s を下回る要求数 | 399 のうち 226 | 398 のうち 0 |
表 1: ワーカーのいずれかが停止した後の、コールドリスタートとシャドウエンジン回復の比較
283 秒を要するコールドリスタートのベースラインと比較して、シャドウエンジン回復にはわずか 7.3 秒しかかかりません(故障検出に 1.7 秒、プロモーションに 5.6 秒)。これにより、障害発生後の TTFT とデコードレートが大幅に改善され、SLA の違反をほぼ回避できるようになります。
## 現在の範囲と今後のステップ
Kubernetes 上の推論ワークロードに対して高速な回復が可能であることを検証したことで、実装の安定化とより広範なワークロードへのサポート拡大に取り組んでいます。シャドウエンジン回復機能は、今後数ヶ月にかけて段階的に展開されます。
現在のパブリックプレビューにはいくつかの制限とデプロイ要件があります。
- シャドウエンジン回復は一般的なエンジンプロセスの障害に対応していますが、ハードウェア、ノード、またはマルチノードの障害まではカバーしておらず、これらについては標準的な再スケジューリングに依存します。
- Kubernetes 上で Dynamic Resource Allocation (DRA) の利用が必要です。そのため、クラスターは DRA が有効化された Kubernetes 1.34 以降であり、NVIDIA GPU DRA ドライバーがインストールされている必要があります。
- Dynamo Snapshot と回復機能を組み合わせることで、シャドウの初期化中に発生する競合を最小限に抑えることができます。
- プロモーションされたシャドウは空の KV キャッシュから始まるため、切り替え直後の TTFT にわずかな増加が見られます。プロモーション時にキャッシュ状態(プレフィックスキャッシュインデックスおよびキャッシュメモリ自体)を引き継ぐことは、現在取り組んでいる主要な課題です。
vLLM は主要なサポート対象バックエンドです。
シャドウエンジン回復を試すには、まず [Kubernetes のクイックスタート](https://docs.nvidia.com/dynamo/cli/getting-started/quickstart) を実行してデプロイを起動してください。その後、シャドウエンジン回復のデプロイワークフローに従い、完全なマニフェストとして [vLLM フェイルオーバー例](https://github.com/ai-dynamo/dynamo/blob/main/examples/backends/vllm/deploy/agg_failover.yaml) を利用します。
質問やバグ報告、貢献については、[ai-dynamo/dynamo リポジトリ](https://github.com/ai-dynamo/dynamo) までお問い合わせください。今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み