DeepInferの内部: DeepSeek V4.1-Flashのアーキテクチャ
DeepInferはDeepSeekのV4.1-Flash推論アーキテクチャであり、最も面白いのは個々のカーネルではない。大規模GPUクラスタが自分自身を待たずに済むようにする、スケジューリングとメモリの判断の集積だ。本番環境の注意点を添えて、順に見ていく。
DeepInferはV4.1-Flash向けのDeepSeekのオープンソース推論アーキテクチャだ。うまく読むには3つの層を分ける必要がある。モデル、エンジン、サービスだ。モデルはV4.1-Flash。エンジンが本ページの主題であり、サービスはDeepSeekが手元に残した部分にあたる。
推論エンジンが実際にやること
学習済みモデルは重みの塊にすぎない。それをサービングするとは、リクエストに応答することだ。プロンプトを読み、モデルを走らせ、トークンを生成して返す。それを、高価なハードウェアを無駄にせず、多数のユーザーに対して同時に行う。
コストの大半は2つのフェーズが占める。
- Prefillはプロンプトを読み、KV cacheを構築する。計算量が多く、多数のプロンプトトークンを並列に処理できる。
- Decodeは1ステップに1トークンを生成する。各ステップでKV cacheとモデルの一部を読むため、メモリ帯域に強く依存し、ステップあたりのレイテンシに敏感だ。
サービングの最適化のほとんどは、どちらかのフェーズを安くするか、別の処理と重ねる試みだ。DeepInferの機能はこの分割にきれいに対応している。
デプロイ構成: EPD、Wide-EP、そして大量のGPU
DeepSeekのQ&Aは、本番のV4.1システムをVision-Encoder / Prefill / Decode(E/P/D)のデプロイとして説明している。
分割する理由は、prefillとdecodeが求めるハードウェアの形が違うからだ。prefillは計算律速、decodeはメモリ律速である。同じプールに載せれば妥協が強いられる。分ければ各段を独立にスケールできるが、その代償としてプール間でKV cacheを移動させ、性質の異なる2つのワークロードの負荷を調整する必要がある。
DeepSeekの本番環境の数字は次のとおり。
| 段 | 並列構成 | 理由 |
|---|---|---|
| Prefill | EP2–8 / DP2–8 | HBMに収まる最小のEP/DPを使う。prefillは計算律速。 |
| Decode | EP64–128 / DP64–128(Wide-EP) | 使える最大のEP/DPを使う。decodeはメモリトラフィック律速。 |
| ビジョンエンコーダ | 1インスタンス1 GPU | 小さいモデル。速いカードを無駄にしない。 |
| TP / CP | 本番では使わない | オープンソースのエンジンはexamplesでCPを公開しているが、本番構成の説明ではTP/CPを使っていない。 |
DeepSeekは、効率的に動く最小単位をprefill 64 GPU + decode 64 GPUと呼んでいる。1P + 1Dの構成もデプロイ可能だが、推奨されるdecode構成はEP64以上なので、小規模クラスタでは同じ効率は出ない。
エキスパートの負荷分散: 冗長コピーと定期的な再配置
MoEのルーティングは均等ではない。熱いエキスパートもあれば、ほとんど使われないエキスパートもある。静的な割り当てはGPUを無駄にする。DeepSeekのEPLB(expert-parallel load balancing)は冗長エキスパート、つまりホットなエキスパートのレプリカを追加し、直近の負荷に基づいてエキスパートをGPUに定期的に再割り当てする。
Q&Aに書かれている仕組みは次のとおり。
- 各GPUは通常のエキスパートに加えて、少数の冗長エキスパートを保持する。
- システムは直近Nステップにわたる各エキスパートの負荷を記録する。
- MステップごとにエキスパートをGPUに再割り当てし、NVLinkドメイン内で対称メモリを使って重みを移動する。
| 段 | 冗長エキスパート | 統計ウィンドウ | 再割り当て | 実測moe_lb |
|---|---|---|---|---|
| Prefill | GPUあたり4(開始時) | 100ステップ | 1,000ステップごと | ≈1.03–1.07 |
| Decode | GPUあたり1(開始時) | 1,000ステップ | 10,000ステップごと | 1.090 |
moe_lbは最遅ランクを平均で割った値だ。1.09なら、最も遅いGPUは平均より約9%多く仕事をしている。decodeの規模では厳しい数字であり、同時に、最速のGPUもバリアで待つことを意味する。
moe_lbを1.074 / 1.045とし、中国語のZhihu記事は1.0320 / 1.0618としている。decodeの値(1.090)は両者で一致する。本サイトではprefillは範囲で示し、decodeは安定した値を使う。DSpark: 検証の計算を、効くところにだけ使う
投機的デコードはdraftモデルで複数のトークンを提案し、それを1パスで検証する。draftが当たれば、1回の検証コストで複数トークンが得られる。外れればフォールバックする。
素朴な実装は固定数のdraftを検証する。DSparkの工夫は可変長検証にある。confidence headが各draftトークンの受容確率を予測し、スケジューラが実効スループットを最大化するprefix部分集合を選ぶ。
DeepSeekは、投機的デコードのdraftモデルを学習・評価するためのMITライセンスのコードベースDeepSpecも公開している。DSpark、DFlash、Eagle3を扱い、DeepInferエンジンとは別物だ。
DeepSeekの本番環境での測定値は次のとおり。
| 指標 | 固定5 | 動的長 |
|---|---|---|
| 1ステップあたりの検証draftトークン数 | 5.00 | 3.2–4.4 |
| 平均受容長 | 3.29 | 3.20 |
| 本番動作点でのスループット(約60 seqs/rank) | — | +4–7% |
| 96 seqs/rankでのスループット | — | +11% |
読み方が重要だ。検証の仕事量は約30%減る一方、受容長はほとんど変わらない。高並列では差し引きでプラスになる。1ランクあたり16シーケンスでは、表は小さな損失(−1.5%)を示している。いいことずくめではない。負荷依存の最適化なのだ。
リリースにおけるdraft長のデフォルト上限は5だ。一方、公開されているdecodeチャートはnextn=3 fixedとトークンあたり75%の受容率を前提にしている。これは測定時の構成であり、デフォルトのデプロイ構成ではない。
SWA bounded replay: ミスを安くし、キャッシュを保存しない設計へ
sliding-window attention(SWA)は、直近のトークンだけを完全なattentionで保持する。V4.1は128トークンのウィンドウを使う。SWAのKV cacheが欠けていると、正確な復元は高くつく。各デコーダ層のウィンドウが下の層に依存するため、20層にわたって状態を再構築すると、およそ2,560トークン・層の再実行(20 × 128)になる。
SWA bounded replayは、意図的に近似する。
- 直近128トークンだけを再実行する。
- 再実行の開始位置でattentionウィンドウを打ち切る。位置iは
[max(s, i−127), i]だけを見る。 - 近似されたSWA KV cacheを受け入れ、再計算コストを有界かつ一定に保つ。
リリースのV4.1デフォルト設定は140トークンのサフィックスを保持する(DEEPINFER_YOCO_PREFILL_KEEP_TOKENS=140)。余分な領域は、ウィンドウと投機的なバックトラックを覆うためだ。
計算を節約する以上に重要なのは、これによってSWA KVを永続化しない判断が合理的になることだ。V4.1の永続KV cacheはグローバルKVを保存し、SWA KVは保存しない。その結果、フットプリントはV4のおよそ8分の1に縮む。グローバルKV自体もトークンあたり約890バイトに圧縮され、V4-Flashのおよそ4分の1になる。
Bounded replayはビット単位で完全ではない。DeepSeekは品質の損失は無視できると述べている。vLLMは同じアイデアを独自実装でGSM8KとGPQAに対して検証し、差はおよそ1.5標準誤差以内だったと報告した。これは手法が妥当だという証拠であり、DeepInferの特定のコードを検証したものではない。
非同期スケジューリング: GPUをCPUの邪魔から遠ざける
decodeの1ステップは次のように進む。
schedule(N) → forward(N) → sample(N) → post-process(N)
scheduleとpost-processはCPUの仕事だ。post-process(N)の前に、CPUはGPUからsample(N)の結果を受け取る必要がある。この同期のあいだ、CPUが結果を処理して次のバッチをスケジュールする間、GPUは遊んでしまう。
DeepInferはこの2つを重ねる。
GPU: forward(N) → sample(N)
CPU: schedule(N+1) → launch_forward(N+1) → post-process(N−1) → launch_sample(N+1)
アイデア自体は新しくない。DeepSeekはSGLangとNanoFlowを引いている。だが実装はリリースに含まれ、デフォルトで有効になっている。ベンチマーク用のカーネルとサービングエンジンの差を生むのは、こうした作業だという好例である。
バッチ不変推論と決定論的サンプリング
動的バッチングは浮動小数点演算のリダクション順序を変える。同じプロンプトでも、どのリクエストが同じバッチに同居したかによってlogitsがわずかに変わりうる。チャットでは通常見えない。ベンチマーク、監査、エージェント実行の再現では問題になる。
DeepInferは2段階の制御を用意している。
- バッチ不変推論(
DEEPINFER_BATCH_INVARIANT=1): バッチ構成が変わっても結果が一貫する。 - 決定論的サンプリング: 同じ入力トークンと同じサンプリングパラメータからは同じ出力が得られる。バッチ不変モード、MTP可変長デコードの無効化(
DEEPINFER_ENABLE_MTP_VARLEN=0)、固定のseq_seedが必要だ。
どちらもこのリリースではNVIDIA専用だ。主役の機能ではないが、真剣な評価チームが気づく類のものではある。
構造化出力: プロンプトではなく文法を制約する
構造化出力は、生成をregex、JSON Schema、EBNF文法のいずれかに制約する。DeepSeekの本番設計では、制約を別マシン上で文法オートマトンにコンパイルし、decodeの各ステップでトークンマスクを適用する。コンパイルと推論が分離されているため、リクエストはエンジンに入る前にコンパイル済みの文法を選び取れる。
リリースでのAPIはSamplingParams(so_args={"schema_type": ..., "schema": ...})だ。オフラインのexampleでは--check_structured_outputでregex、JSON、EBNFのチェックを実行し、通常のEOS終了を検証できる。
これはDeepInfer固有ではない。制約付きデコードはよく知られた手法だ。とはいえサービングエンジンの中にあると、エージェントや抽出のワークロードでは便利である。
DeepSeek Recipe: 「API互換」のもう半分
推論エンジンはトークンを計算する。APIサービスには、さらに次のことが要る。
- Chat Completions、Responses、Messagesのリクエストを受け付ける。
- thinkingモード、ツール、画像を含む、モデルのプロンプト形式をレンダリングする。
- ユーザーテキストに特殊トークンを注入させずに、テキストをトークンIDへ符号化する。
- ストリーミング出力をチャンク境界をまたいでパースする。
- 推論内容、ツール呼び出し、停止シーケンスをプロトコルのレスポンスに戻す。
deepseek-recipeがそれを担う。MITライセンスの別リポジトリで、Pythonバインディング付きのRustライブラリとexampleサーバーからなる。DeepSeekは処理ロジックが公式APIと整合していると述べており、第三者のデプロイでも公式サービスと同じ挙動を狙える。
見落とせない詳細が2つある。
- 特殊トークン注入の防御。 ユーザーが
<|User|>や<|image|>と入力しても、Recipeはそれを制御トークンではなく通常のテキストとして符号化する。ユーザーコンテンツをロール境界と誤認させることはできない。 - 分割並列トークナイズ。 特殊トークンとその位置はプロンプト構築時に既知なので、その間の通常テキスト区間を独立に符号化して連結できる。長いコンテキストでのトークナイズ遅延を減らせる。
DeepInferをサービングスタックとして評価するなら、Recipeはエンジンと同じくらい注目に値する。エンジンは高価な部分であり、RecipeはAPIの手触りを正しくする部分だ。
新しいアイデアか、古いアイデアか
| 概念 | 位置づけ | DeepSeekが加えたもの |
|---|---|---|
| 投機的デコード | 確立済み | DSparkの信頼度に基づく可変長検証 |
| sliding-window attention | 確立済み | Bounded replayと、SWA KVを永続化しない設計 |
| expert parallelism | 確立済み | 64〜128 GPUでのWide-EPと、本番向けのEPLBチューニング |
| 連続バッチング / 非同期スケジューリング | 確立済み | デフォルト有効の完全な実装 |
| 構造化出力 | 確立済み | エンジンへの統合と、文法コンパイルの分離 |
| バッチ不変 / 決定論的推論 | やや珍しい | 条件を明記した明示的サポート(NVIDIAのみ) |
| 専用3FSクラスタ上のKV cache | DeepSeek固有 | 100 PiB、3/7日TTL、マシンをまたぐprefixヒット |
| CED + SWA replayの協調設計 | DeepSeek固有 | モデルアーキテクチャとエンジンの同時チューニング |
正直に整理すればこうだ。DeepSeekはこれらのプリミティブの多くを発明していない。貢献は統合にあり、そして本番のチューニングを公開する姿勢にある。
本番設計 ≠ オープンソースコード
EPD、EPLB、KV cache、ロードバランシングの各節はすべて、Q&Aに記されたDeepSeekの本番システムを説明している。リリースにはKV cacheシステム、VE/Prefill/Decodeの分離、データ並列ロードバランシングは含まれない。本番設計を読むことはエンジンを理解する助けになるが、リポジトリの機能一覧ではない。
Q&Aが与えてくれるのは、コードの背後にある判断の地図だ。なぜWide-EPなのか、なぜ64+64なのか、なぜ3FSなのか、なぜ3/7日のTTLなのか、なぜbounded replayなのか、なぜ可変長検証なのか。別のラボのエンジニアにとって、この地図こそがリリースで最も価値のある部分だ。コードがエンジンの境界で止まっていても、である。
次は2つのチャートの読み方、欠けている部分がデプロイに何を意味するか、あるいはサービング比較へ: vLLM、SGLang、TensorRT-LLM。