DeepEP

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

3posts · 30d
Nov 30 posts
  1. Zenn · · @nanakanok

    MoE推論の可視化してみる ! この記事で紹介するページは、MoE 推論の通信の流れを説明するための模式図です。経路・スイッチの通過数・データ量はトポロジと公開されているモデルの config から計算していますが、レイテンシやスループットの数値は出しません。性能評価ではありません。個人で作った教材であり、実装や論文の解釈に誤りが含まれる可能性があります。 はじめに LLM の推論基盤では、Prefill と Decode を別の GPU に分ける PD 分離や、Attention と FFN(Expert)を別の GPU に分ける AF 分離が広がっています。こうした構成の話をすると、すぐに「その通信はどの GPU からどの GPU へ、どのスイッチを通って流れるのか」という問いにぶつかります。Scale-up(ノード内)で済むのか、Scale-out(Leaf-Spine)に出るのか。レール最適化した配線なら Spine を通らずに済むのか。 文章や静止画だけでは、分かりにくいと感じていました。そこで、構成を切り替えながら通信の流れをアニメーションで見られるページを作りました。 nanakanok.github.io この記事では、ページで何が見られるか、どういうモデルで描いているか、そしてページを触って分かることを紹介します。 1. 何が見られるか 画面の中央が 4 ノード × 8 GPU のトポロジ、右が説明パネル、下が操作バーです。 主な操作は次のとおりです。 操作 内容 ネットワーク Scale-up のみ / Scale-up + Scale-out を切り替える PD 分離・AF 分離 独立した 2 つのトグル。組み合わせで 4 通りの構成になる レール最適化 Leaf への配線を、レール最適化(Leaf 8 台)と ToR 型(Leaf 4 台)で切り替える 詳細設定 「Decode も Scale-up 中継する」、ECMP ハッシュの再抽選 プロンプト 自由入力かプリセット。トークン数が KV やトークン送信のデータ量に反映される ステップ説明 1 つのバッチを 1 ステップずつ追う。追跡中のリクエストを強調色で描く 並行動作(自動再生) 複数のバッチが重なって進む様子を流す GPU、スイッチ、リンク、動いている粒にマウスを載せると概要が出ます。クリックすると一時停止し、その要素の詳細を右パネルに固定します。たとえばリンクをクリックすると、そのリンクを通っている通信の一覧と、方向ごとのデータ量が見られます。 ノードの下には、追跡中のリクエストが通る代表 GPU の内部をカードで表示しています。処理ブロック(Embed → Attention → KV → Router → Experts → Combine → Head)のうち、いま動いているものが光ります。そのほかに、この GPU が持つ Expert のうち選ばれたもの、HBM の内訳(重み / KV / activation)も表示します。ブロックをクリックすると、Router が選んだ top-k の Expert と重みや、MLA と GQA の違いなどを右パネルで確認できます。 2. どういうモデルで描いているか トポロジ 項目 内容 ノード 8 GPU + Scale-up Switch。GPU ごとに Scale-out 用の NIC が 1 枚(8 レール) 規模 4 ノード × 8 GPU = 32 GPU、Spine 4 台 レール最適化 Leaf 8 台。各ノードの GPU i は Leaf i につながる ToR 型 Leaf 4 台。ノード n の 8 枚の NIC はすべて Leaf n につながる 容量 どちらも 1:1 のノンブロッキング。NIC 数、uplink の本数、Spine のポート数を揃えている レールの有無を比べるときに設備量の違いが混ざらないよう、ToR 型でも uplink の総数は同じ 32 本にしています(Leaf から各 Spine へ 2 本ずつ)。違うのは「NIC をどの Leaf に配線するか」だけです。 「Scale-up Switch」「Scale-up リンク」は、NVSwitch / NVLink、UALink、SUE(Scale-Up Ethernet)などの総称として使っています。 推論の構成 基準のモデルは DeepSeek-V3 相当の MoE です(公開 config: hidden 7168、61 層のうち先頭 3 層が dense、routed expert 256 個中 8 個を選択、shared expert 1 個)。 Attention は DP attention(TP=1)として描いています。1 リクエストの Attention と KV Cache は 1 GPU が担当します。TP を使うと MLA の圧縮 KV が各 rank に重複して置かれ、KV 転送の説明が複雑になります。DP attention なら KV 転送は GPU どうしの 1 対 1 になります。 構成 Attention routed experts 統合型 全 32 GPU 全 32 GPU(EP=32) PD 分離 Prefill: ノード 0-1 / Decode: ノード 2-3 各側の 16 GPU(EP=16) AF 分離 ノード 0-1 ノード 2-3(EP=16) PD+AF Prefill: ノード 0-1 / Decode-A: ノード 2 Decode-F: ノード 3(EP=8) AF 分離では、router、shared expert、dense 層、最後の合算と residual を Attention 側が持ちます。F 側は routed expert だけを持ち、GPU ごとに重み付きの部分和を 1 本にまとめて返します。Attention 側の router は、選んだ Expert を持つ F 側の GPU へトークンを直接送ります(M:N)。 転送方式 通信の目的(KV / dispatch / combine / A→F / F→A)と転送方式(direct / Scale-up 中継)を、別の属性として扱っています。転送方式の既定は DeepEP の 2 つのモードに合わせました。 通信 既定の転送方式 理由 Prefill の dispatch / combine Scale-up 中継(DeepEP Normal) スループット重視。dispatch は受信ノード内で配り、combine は送信ノード内で集約してから返す Decode の dispatch / combine、A↔F direct(DeepEP Low-Latency) レイテンシ重視。中継の段数を減らす KV 転送 direct(NIXL などの RDMA 1 対 1) 集団通信ではない ECMP とデータ量 ECMP は、RoCEv2・フローごとの静的ハッシュ・adaptive routing なしを前提にしています。実際に送受信する NIC と QP ごとの送信元ポートからハッシュを取り、送信 Leaf の uplink と、Spine から宛先 Leaf への出力リンクの両方を決めます。シード値は固定で、詳細設定から再抽選できます。 データ量は概算として表示します。 種類 式 KV トークン数 × 61 層 × (512 + 64) × 2 B(BF16)= 70,272 B/トークン 送信(dispatch、A→F) 7168 × 1 B(FP8)× 送り先の GPU 数 返送(combine、F→A) 7168 × 2 B(BF16)× 送り先の GPU 数 同じ GPU 上の複数の Expert へ送る分は 1 回にまとめます。Scale-up 中継を使うときは、宛先ノードごとに RDMA を 1 回だけ送り、ノード内で配ります。「Expert を 8 個選ぶ」ことは「ネットワーク送信が必ず 8 回」を意味しません。 3. ページを触って分かること ここからの数値は、プリセット「中くらいの依頼」(追跡中のリクエストは 82 トークン、バッチは 32 リクエスト)で、ページと同じモデルから計算した値です。データ量は代表 1 層あたりの値です。 レール最適化は、同じレールの通信を Leaf 1 台に閉じ込める PD 分離では、スケジューラが Prefill の開始時に Decode 側の GPU を予約します。このページでは、同じ GPU 番号(=同じレール)の GPU を優先して選びます。 KV 転送(PD 分離) Scale-out スイッチの通過数 Spine を通るデータ量 最大リンク負荷(片方向) レール最適化 1 0 MB 16.4 MB ToR 型 3 179 MB 32.2 MB レール最適化では、KV 転送は Leaf を 1 台通るだけで済みます。ToR 型では Leaf がノードごとに分かれているので、ノード間の転送は必ず Leaf → Spine → Leaf を通ります。ToR 型の最大リンク負荷が 2 倍になっているのは、ECMP のハッシュで一部の uplink に流れが偏ったためです。詳細設定でハッシュを再抽選すると、偏り方が変わります。偏りはハッシュの当たり外れで生じるもので、トポロジの必然ではありません。 なお、「1 スイッチで済む」のは、この図では各レールが 1 台の Leaf に収まっているからです。大規模な構成で同じレールが複数の Leaf にまたがれば、Spine を通る場合があります。 Decode では、レール最適化でも Spine を通る Prefill の dispatch はレール最適化なら Spine を通りません(Spine を通るデータ量 0 MB)。Scale-up 中継で宛先のレールへ寄せてから送るためです。一方、Decode では中継しないので、レールをまたぐ送信は Spine を通ります。 Decode の dispatch(PD 分離、レール最適化) RDMA の量 Spine を通るデータ量 既定(direct) 0.80 MB 0.68 MB 「Decode も Scale-up 中継する」を ON 0.23 MB 0 MB 「Prefill はスループット重視で中継し、Decode はレイテンシ重視で直接送る。そのため Decode では Spine の設計が効いてくる」というトレードオフが、トグル 1 つで見えます。中継を ON にすると Spine は避けられますが、そのぶんノード内の中継が 1 段増えます。 ToR 型では、中継しても Spine は避けられない。ただし量は減る 同じ比較を ToR 型で行うと、中継を ON にしても通信は Spine を通ります(スイッチの通過数は 3 のまま)。ただし、宛先ノードへの重複した送信がまとめられるので、Spine を通るデータ量は 0.80 MB から 0.23 MB に減ります。「Spine を避けられるか」と「Spine を通る量を減らせるか」は別の効果だと分かります。 AF 分離の通信は 1 対 1 ではない PD+AF で Decode の A→F を見ると、Decode-A のノード 2 から Decode-F のノード 3 へ、トークンごとに最大 8 台の GPU へ送られます。送り先の GPU 番号はトークンごとにばらばらなので、レール最適化でも既定ではスイッチを 3 台通ります(Spine を通るデータ量 1.10 MB)。AF 分離の通信を「同じ番号の GPU 同士の 1 対 1」と思い込むと、見積もりを誤ります。 並行動作で、分離の利点が見える 「並行動作(自動再生)」に切り替えると、PD 分離では Prefill・層ごとの KV 転送・Decode が同時に進みます。PD 分離なしでは、同じ GPU で Prefill と Decode が交代するので、Prefill の間は Decode が待たされます。AF 分離では、2 つのマイクロバッチがピンポンし、一方が A→F を送っている間にもう一方が F→A を返すので、A と F が同時に動きます。 ただし、マイクロバッチ 2 個は「通信を計算と重ねる一例」として描いています。最適な数でも、通信を完全に隠せることの保証でもありません。 軽量なモデルなら Scale-up だけで足りる 「Scale-up のみ」に切り替えると、基準のモデルを Qwen3-30B-A3B 相当の軽量 MoE に切り替えます(hidden 2048、48 層、128 Expert 中 8 個、GQA の KV 4 ヘッド × 128)。重みは BF16 でも約 61 GB と 1 ノードに十分収まるので、4 ノードはそれぞれ独立したレプリカとして動きます。すべての通信がノード内で完結し、Leaf-Spine は薄く表示されたまま使われません。 GPU の中では、重みが HBM の大半を占める 代表 GPU のカードを見ると、PD 分離の Prefill GPU の HBM は約 58 GB で、ほぼすべてが重みです(routed expert の 1/16 と、Expert 以外の重み)。KV はプロンプトが短いうちはわずかですが、Prefill が進むと増え、KV 転送で Decode 側へ移ります。プリセット「長い文書の要約」を選ぶと、KV の割合が増える様子が分かります。Attention のブロックを開くと、Decode で 1 トークンを作るたびに文脈の長さに比例した KV を読むこと、つまり Decode がメモリ帯域に縛られる理由が数値で示されます。 4. 割り切ったこと 32 GPU に縮小した模式図です。並列化も DeepSeek-V3 の実運用の配置とは異なり、この配置でモデルが収まることは保証しません。 レイテンシやスループットは表示しません。帯域の前提に議論が逸れ、数字が独り歩きしやすいためです。 出力文はダミーで、トークン分割も模式的です。本物の LLM は動かしていません。 ECMP の偏りはハッシュの一例です。QP を 1 本とするのも説明用の仮定です。 MTP(投機的デコード)と group-limited routing は再現していません。 まとめ PD 分離・AF 分離・Scale-up / Scale-out・レール最適化の有無を切り替えながら、MoE 推論の通信がどの経路を流れるかを見られるページを作りました。 触ってみると、レール最適化の効果は KV 転送や Prefill の dispatch でははっきり出る一方、Decode(中継しない)や AF 分離の M:N 通信ではレールをまたいで Spine を通ることが分かります。ToR 型では中継しても Spine は避けられませんが、通る量は減らせます。 軽量なモデルなら Scale-up だけで足り、Leaf-Spine は使われません。 参考 inference-fabric-viz(ページ) / リポジトリ DeepSeek-V3 Technical Report DeepSeek-V3 config.json DeepEP(参照した版は v1.2.1) Doubling all2all Performance with NVIDIA Collective Communication Library 2.12(NCCL PXN) MegaScale-Infer: Serving Mixture-of-Experts at Scale with Disaggregated Expert Parallelism Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving Qwen3-30B-A3B config.json

  2. Zenn · · @tosshi

    NCCL Roadmap Nov 2026 - Jan 2027 の解説 はじめに ! NCCL 奥がふかすぎる。。。。にゃ。。。 NVIDIA が公開した NCCL Roadmap: Nov 2026 - Jan 2027 (GitHub Issue #2486) から、大規模分散学習・推論に携わるエンジニアが押さえるべきポイントを解説します。前回のロードマップの解説は「NCCL Roadmap Aug-Oct 2026 の解説」、そこで挙げた項目の現在までの実装状況は「NCCL 2.32.3 でロードマップはどう実装されたか」にあります。GIN の基本は前回の解説を前提にします。 この記事では、新しい概念の GENK と Flow、AWS EFA と GIN の現状、注目機能 2 つを扱います。調査は 2026 年 10 月 29 日に行い、まだリリースされていないコードは、staging ブランチを次のリリースの候補とみなして読んでいます。 実装状況の確かめ方 NVIDIA/nccl、aws-ofi-nccl、amazon-contributing/DeepEP、NVIDIA/nccl-extensions の公開ブランチを手元に取得し、commit の履歴とソースを読んで確かめました。PR と Issue の状態 (open か、マージされたか、閉じた日) は GitHub で確かめています。記事のソースへのリンクは、確かめたときの commit に固定しています。 NCCL は master、staging、dev の 3 本のブランチを公開していて、staging には 2.32.5-1 の版番号を付けた commit があり、その後に 2.32.6a0 に上がっています。ロードマップは「Coming Soon: NCCL 2.32 Update 1」の版番号を書いていませんが、この記事では staging のコードをその候補として読みます。 今回のロードマップの項目のうち、この記事で扱うものと、前回のロードマップの近い項目は次のとおりです。対応は筆者の読みです。 今回のロードマップの項目 前回のロードマップの近い項目 General Kernels (GENK) Unify legacy kernels using Device API Flow Device API More Device API primitives GIN Backend Improvements GIN backend improvements CFT を使う階層型カーネル Compute Fabric Transport (CFT) through Device API New Enqueue Pipeline Legacy and symmetric-kernel host-side unification ロードマップには、内部のメモリの削減、RAS の進み具合の監視、RMA の profiling など、この記事で扱わない項目もあります。 Device API とは何か NCCL の API の全体像 ロードマップの項目を説明する前に、まず背景知識として NCCL の API を整理します。NCCL の API は、Host API、Device API、plugin API の 3 つに分けられます。Host API と Device API の仕様は NCCL の公式文書にあり、この記事の表はその章立てに沿っています。plugin API は公式文書の API の章には無く、リポジトリの plugins ディレクトリに plugin の種類ごとの説明があります。 API 何をするか 例 Host API CPU から呼んで、communicator (通信に参加する GPU の集まり) の作成や集団通信を NCCL に頼みます。集団通信では、NCCL がアルゴリズムを選び、NCCL のカーネルを GPU で起動します。利用者の計算は別のカーネルです ncclCommInitRank、ncclAllReduce Device API 利用者が書いた CUDA カーネルの中から、ほかの GPU との通信を直接呼びます (2.28 から)。計算と通信を 1 つのカーネルに入れられます。使う前の準備には Host API を使います GIN、LSA plugin API NCCL のほうから呼ぶ、下の部品の差し替え口です。ネットワークへの送受信や、アルゴリズムの選択の調整などを、NCCL の外の実装に任せます net、GIN。説明は plugins にあります。aws-ofi-nccl は EFA 用の plugin 誰が NCCL を呼ぶか NCCL を呼ぶのは、多くの場合アプリ自身ではなく、間に入るフレームワークやライブラリです。主な呼び手を、ソースで確かめた範囲で並べます。 呼び手 どう呼ぶか 使う API PyTorch の torch.distributed (backend "nccl") C++ の ProcessGroupNCCL が、ncclAllReduce などを直接呼びます Host API PyTorch の backend "nccl4py" (torch.distributed._nccl4py) Python で書いた backend が、nccl4py を通して呼びます。init_process_group("nccl4py") で選びます Host API nccl4py NVIDIA の公式の Python の bindings。Cython で libnccl を呼び、PyTorch の tensor や CuPy の配列をそのまま渡せます。実験的な CuTe DSL の部品もあります 主に Host API vLLM の PyNccl Python の ctypes で libnccl を読み込んで呼びます Host API PyTorch の symmetric memory の演算、DeepEP、NCCL EP 自分の CUDA カーネルの中から通信を呼びます。準備には Host API で window (次の節で説明します) を登録し、device communicator を作ります Device API と Host API aws-ofi-nccl など NCCL のほうから呼ばれます。NCCL が EFA などのネットワークに送るときの下の部品です。InfiniBand には NCCL に組み込みの経路もあります plugin API Device API は何のためにあるか Host API で通信を頼むと、通信は NCCL のカーネル 1 回分の単位になり、利用者の計算とは別のカーネルになります。計算の途中で決まった相手に少しずつ送りたい場合や、計算と通信を細かく重ねたい場合には、この単位が粗すぎます。たとえば MoE のトークンの振り分けでは、どのトークンをどの GPU に送るかが計算の途中で決まります。 Device API は、利用者のカーネルの中から、ほかの GPU のメモリへ直接データを動かせるようにするための API です。NCCL の Device API の例は、計算と通信を分けて順に行う従来のやり方に対して、カーネルの中で両方を細かく混ぜることで、待ち時間を減らし処理量を上げられると説明しています。 GPU のカーネルからほかの GPU に届く経路はいくつかあり、Device API は経路ごとに部品を用意しています。同じノードで NVLink や PCIe の P2P でつながった相手には、相手のメモリを普通の読み書きの命令で触れます (LSA)。NVLink のスイッチが複数の宛先への書き込みや足し合わせを引き受けられるシステムでは、Multimem を使います。ノードをまたぐ相手には、NIC を通して put (相手のメモリへの書き込み) や get (相手のメモリからの読み出し) を出します (GIN)。どちらも、相手が何も呼ばない片側通信です。CFT は、相手のメモリを番地 (ポインタ) で触る代わりに、CUDA が用意する宛先の番号 (logical endpoint) とオフセットを指定して put や get を出す部品で、Blackwell 以降の GPU で使えます。これらと組み合わせて使う、足し合わせやコピーの部品 (reduce と copy) も用意されています。 GIN の仕組みは、前回の解説の「GIN とは何か」で説明しました。LSA は後の GENK と Flow の節で、CFT は注目機能の節で扱います。Multimem と reduce と copy の部品は、この記事では詳しく扱いません。 どの部品を使う場合も、準備は利用者が CPU で Host API を呼んで行います。通信に使うバッファを、全ランクで同じ形に対応付けた領域 (symmetric memory window) として登録し、カーネルが使う資源を指定して device communicator を作り、それを渡して自分のカーネルを起動します。手順の例は NCCL の文書にあります。GIN を使うカーネルは、NCCL を更新したら作り直す必要があると文書は書いています。次の節からは、この Device API の上に加わる新しい部品とカーネルを見ていきます。 GENK と Flow とは何か ! GENK と Flow は、まだリリースされておらず staging と dev にだけあるコードです。この節は staging の実装から読み取った内容で、リリースまでに変わる可能性があります。staging で試すには、ビルドのときに SYM_GENK=1 を指定し、実行のときに NCCL_SYM_GENK_ENABLE=1 を設定する必要があります。 概要 Flow は、前の節の LSA と GIN の上に作られた、集団通信の部品を提供する Device API です。ロードマップは Flow を「LSA と GIN の両方で動く、高水準の Device API」と説明しています。LSA は前の節で触れた、相手の GPU のメモリを普通の読み書きの命令で触る部品です。 GENK (General Kernels) は、NCCL が自分の Ring と Tree の集団通信を、この Flow の上で作り直したカーネルの一群です。Ring では AllGather、ReduceScatter、Broadcast、Reduce、AllReduce を、Tree では AllReduce を実装しています。 前回のロードマップには「Unify legacy kernels using Device API」という項目がありました。筆者は、GENK をこの項目につながる取り組みと読んでいます。今回のロードマップは、選んだプラットフォームで GENK を既定にし、古いカーネルを置き換えるとしています。あわせて性能モデルを 1 つにまとめ、どの実装を選ぶかを同じ物差しで決めるとしています。 staging では、NCCL 自身が同じ Flow で集団通信を組んでいます。Flow がリリースに入れば、利用者も NCCL の内部と同じ部品で通信カーネルを書けます。 NCCL の集団通信には、GENK の前から 2 種類のカーネルがあります。 legacy kernels: NCCL に最初からある Ring や Tree のカーネルです。経路の違いは、CPU の側が準備する transport (NVLink や PCIe の P2P、ネットワークなど) が受け持ち、ネットワークでは CPU の proxy スレッドが NIC に渡します。 symmetric カーネル: 全ランクが同じ形で登録したバッファ (symmetric memory window) を集団通信に渡したときに使える、新しいカーネルです。相手のバッファの番地が分かるので、Device API の LSA などで相手のメモリを直接読み書きします。いまあるものは、NVLink の直結を前提に、場面ごとに作り込まれています (表の「特化した symmetric カーネル」)。 GENK は、symmetric カーネルと同じ Device API の作りで、legacy kernels と同じくらい広い経路で動くものです。Ring で隣の GPU にデータを渡す場面で比べると、次のようになります。 隣の GPU との経路 legacy kernels 特化した symmetric カーネル GENK NVLink 動く 動く 動く (LSA) PCIe の P2P 動く 使えない 動く (LSA) 別のノード (ネットワーク) 動く 一部の種類だけ動く (GIN) 動く (GIN) 表は、Hopper 以降の GPU で GENK を有効にした場合についてソースから読んだもので、動かして確かめたものではありません。PCIe の行は CUDA P2P が使える場合、GENK のネットワークの行は GIN Proxy (GPU の代わりに CPU のスレッドが NIC に送る GIN のバックエンド) が使える場合です。 特化した symmetric カーネルは、PCIe だけでつながったノードでは候補から外れます。GENK では、隣の GPU ごとに Flow が LSA か GIN かを実行時に選ぶので、同じカーネルのまま NVLink でも PCIe でもネットワークでも動きます。staging のカーネルの選択にも「特化したカーネルは NVLink の直結を要するが、GENK は CUDA P2P の LSA や GIN も使える」というコメントがあります。 利用者の側の例もあります。NCCL の Device API の例には、Transformer の RMSNorm の計算を ReduceScatter と AllGather の通信と 1 つのカーネルにまとめるものがあり、いまは LSA、Multimem、GIN を直接使って、受け取り、足し合わせ、送り出しを書いています。Flow は、NCCL 自身が集団通信に使うこの受け取り、足し合わせ、送り出しの部分を、部品として提供します。 NCCL の文書の Device API の章には、Flow と GENK の説明はまだありません。Flow の使い方は、ヘッダの説明にまとまっていて、Flow processor を足した commit が入口になります。GENK は、カーネルを足した commit と、NCCL の選択に組み込んだ commit が出発点です。 図で [API] のタグを付けた Flow processor、LSA connection、GIN connection は、アプリのカーネルからも呼べる Device API です。cost model、legacy kernels、specialized symmetric kernels、GENK は NCCL の中の部品です。 GIN の signal とは GIN の put は片側通信で、受け手は何も呼ばないので、データがいつ届いたかを自分では知れません。signal は、それを知らせるための、受け手の側に置かれた数です。送り手が put に signal を付けると、データが届いたあとに受け手の数が増え (たとえば 1 増え)、受け手はその数が目標に達するまで待ってから読みます。GIN の基本は、前回の解説の「GIN とは何か」で説明しました。 signal には strong と weak の 2 種類があります。weak signal が「読んでよい」と約束するのは、その signal を付けた put のデータだけです。strong signal は、同じ相手に同じ context (GIN の通信の通り道の 1 本) で先に出した put のデータもすべて読めると約束します。そのため、最後の put にだけ signal を付ければ済みます。 EFA の送り方の SRD は、書き込みが届く順番を保ちません。そのため、最後の put に付けた signal が届いても、前の put のデータが届いたとは限りません。EFA の上の経路のうち、GPU から直接送る EFA GDA が提供するのは weak signal だけです (次の節で説明します)。一方、Flow の GIN の接続は strong signal を必要とします。 AWS EFA 関連アップデートと現在の課題 EFA の 2 つの GIN の経路と signal の種類 ! GENK と Flow の GIN の接続は strong signal を必要とします。EFA の上で strong signal を提供するのは GIN Proxy だけで、GPU から直接送る EFA GDA は weak signal しか提供しません。そのため、EFA の複数ノードで GENK を使うなら Proxy の経路になります。 EFA で GIN を使うときは、使う経路 (GIN のバックエンド) が、カーネルの必要とする種類の signal を提供するかを先に確かめます。NCCL は、カーネルが求める種類の signal を提供できないバックエンドを使わず、提供できる別のバックエンドがあればそちらに切り替え、無ければエラーにすると説明しています。EFA で使う GIN の経路として、ここでは 2 つを比べます。1 つは NCCL の GIN Proxy で、CPU のスレッドが aws-ofi-nccl の RMA の機能を通して EFA に送ります。もう 1 つは EFA GDA で、GPU のカーネルが EFA の送信キューに直接依頼を書きます。aws-ofi-nccl の文書によると、EFA GDA は NCCL_GIN_TYPE=5 で明示したときに使われます。同じ文書は、明示しなければ NCCL 2.31 は EFA で Proxy を使うと書いています。インスタンスやドライバなどの要件も同じ文書にあります。 2 つの経路は、提供する signal が違います。NCCL の Proxy は、strong signal と VA signal (登録した仮想アドレスに置く signal) を使えると報告します。EFA GDA については、aws-ofi-nccl が strong signal も VA signal も使えないと報告し、NCCL の側も番号で指す indexed signal だけを受け付けます。EFA GDA の signal は、EFA の NIC が届いた書き込みを数えるカウンタで作られています。aws-ofi-nccl の文書は、signal と counter の合計が EFA のデバイスあたり 512 個までであることも、制限に挙げています。 図の矢印は、使い手が必要とする signal をバックエンドが提供するかを示します。矢印はソースと文書から描いたもので、どの経路が選ばれるかや、動かした結果を示すものではありません。図の DeepEP の ordered は届く順番を前提にする上流のカーネル、unordered は順番を前提にしない amazon-contributing のフォークのカーネルです。 GENK はノードをまたぐ通信に使う GIN のバックエンドとして Proxy を指定しているので、staging のコードを読む限り、GENK が EFA の上で複数ノードの通信をするなら Proxy の経路を通ります。一方、aws-ofi-nccl の文書は、EFA GDA を使うときに symmetric の GIN カーネルを無効にするよう書いていて、この設定 (NCCL_SYM_GIN_KERNELS_ENABLE=0) にすると複数ノードの GENK は候補から外れます。つまり、EFA GDA を使う設定 (NCCL_GIN_TYPE=5 と NCCL_SYM_GIN_KERNELS_ENABLE=0) では複数ノードの GENK は使われず、複数ノードで GENK を試すときは、この 2 つの環境変数を設定せずに Proxy の経路で動かします。 aws-ofi-nccl v1.22.0 で、EFA GDA の Get がタグの付いた版で使えるようになった Get は、GPU のカーネルが、ほかの GPU のメモリの中身を、持ち主に何もさせずに読み出す操作です。たとえば、手元の番号を見て、ほかの GPU が持つ表の行を取り出すような使い方ができます。Get の意義は「NCCL 2.32.3 でロードマップはどう実装されたか」で説明しました。 その記事の時点では、NCCL 2.32.3 には Get が入っていましたが、aws-ofi-nccl の側の対応はタグの無い master にしかありませんでした。2026 年 10 月 22 日 (日本時間) の v1.22.0 は、NCCL 2.32 が使うキューの形への対応と、Get の完了を数える修正を含む最初のタグです。これで、NCCL 2.32 と aws-ofi-nccl v1.22.0 という、タグの付いた版どうしに、EFA GDA の Get に要る変更がそろいました。v1.22.0 のリリースノートは Get に触れておらず、筆者は動かして確かめていません。 ただし、EFA GDA の Get には、完了を知らせる signal や counter を付けられません。読み出しが終わったかは、出した依頼をまとめて待つ Flush で確かめます。 MoE の通信ライブラリ (DeepEP と NCCL EP) の動き MoE のトークンを担当の expert に配り (dispatch)、計算結果を集める (combine) 通信のライブラリにも動きがありました。DeepEP と NCCL EP はこの同じ役割の候補で、どちらも下で NCCL を使います。DeepEP は 2026 年 9 月 29 日の V2.5 で NVSHMEM への依存を取り除き、ノードをまたぐ通信は NCCL の GIN だけになりました。要件は NCCL 2.32.3 以降です。EFA で DeepEP を動かす取り組みは amazon-contributing/DeepEP のフォークにあり、その詳細は別の記事で整理してみます。 NVIDIA の NCCL EP は NVIDIA/nccl-extensions に移り、NCCL の staging からは、nccl_ep と nccl_m2n のディレクトリが消されました。 注目機能 2 選 CFT を使う階層型カーネル CFT (Compute Fabric Transport) は NCCL 2.31 で Device API に加わった部品で、嬉しさは 2 つあります。1 つ目は、カーネルから直接届く相手を、LSA の範囲より広げられる見込みがあることです。LSA で届く相手は、CUDA P2P で相手のメモリを普通の読み書きの命令で触れる相手 (LSA team) に限られます。CFT は相手を番地ではなく CUDA が配る宛先の番号で指すので、届く範囲は、CUDA が「この番号で届く」と報告する範囲で決まります。前回のロードマップも、CFT を、logical endpoint で届く範囲の相手を宛先の番号で指す通信の形と説明していました。ただし、リリースされた版では、CFT で届く相手の集まり (CFT team) の大きさは既定で LSA team と同じです。 2 つ目は、受け手に届いたことを早く知らせる書き込みがあることです。CFT の普通の put や reduce で受け手に知らせるときは、データを書いたあと、書き込みの完了を確定させ (fence)、合図のフラグを書きます。これが counted な書き込みで、フラグの代わりに、NCCL_WIN_CFT_COUNTED を付けて登録した window の中のカウンタを使います。カウンタはデータより後に進むことが保証されているので、送り手は fence とフラグの書き込みを省けます。staging の文書は、これを低遅延のための操作と説明しています。受け手は、カウンタを見てからデータを読む間に fence を入れる必要があります。 仕組みは次のとおりです。CFT の宛先の番号は、CUDA 13.3 で加わった logical endpoint という仕組みです。NCCL は CPU の側で、宛先の番号を確保し、そこに各 GPU のバッファを結び付けておきます。カーネルは、送りたいデータを shared memory に置き、宛先の番号とオフセットを指定して put を出し、そのあと完了を確かめます。 dev では、CUDA 13.4 以降で CUDA が「logical endpoint で届く範囲」を報告すると、CFT team をその範囲から作ります。その範囲は LSA の範囲の倍数でなければならず、LSA より広い範囲を 1 つの CFT team にできる作りです。NCCL の文書は、CFT がどの物理的な経路を通るかを書いていません。NCCL EP の CFT を使う経路は、1 つの NVLink のドメインの中だけを対象にしています。 ロードマップは、この CFT を使って、AllGather、ReduceScatter、AlltoAll の階層型カーネルを作るとしています。階層型は、近い GPU の間と遠い GPU の間で通信を分ける作りで、LSA の範囲と、それより広い CFT team の範囲を使い分けることになると筆者は読んでいます。master、staging、dev を調べた範囲では、CFT の宛先の集まりの階層の種類は 2.32.3 のコードに定義されていますが、それを使う集団通信のカーネルは見当たりませんでした。 CFT とは CFT が使えるのは、ハードウェア、ドライバ、CUDA が logical endpoint と fabric 用の命令に対応したシステムだけで、例の barrier のプログラムは CUDA 13.3 と SM_100 を要件に挙げています。CFT team を CUDA の報告する範囲 (clique) から作る変更は、dev の 2026 年 9 月 28 日の commit で入り、master と staging にはまだありません。 NCCL EP には、CFT の counted な書き込みで低遅延の dispatch を送る経路が、NCCL_EP_LL_CFT=1 で選んだときだけ使われる形で、2026 年 9 月 16 日の commit から main に入っています。 New Enqueue Pipeline: 呼び出しから起動までを 3 つの層に分ける enqueue は、アプリが呼んだ集団通信や put を、カーネルやコピーの起動に変える NCCL の中の流れです。ロードマップは、これを管理 (Management)、準備 (Preparation)、スケジューリング (Scheduling) の 3 層に分け、制御の流れを簡単にし、カーネルの最適化をしやすくするとしています。 管理と準備の層を含む基本の枠組みは 2.31.2 から入っていて、その時点のスケジューリングの層は既存の経路に戻すだけでした。いまの staging と dev でも、新しい流れは既定で無効です。dev では、Preparation の tuning ですべての集団通信のアルゴリズムやプロトコルを先に選び、classification でその結果だけを使って起動の経路を振り分ける形にしました。経路ごとのスケジューラは、それぞれの仕事を stream ごとに 1 つのキューにまとめます。dev の commit では、新しい流れの symmetric のスケジューラが起動するのは特化した symmetric カーネルだけで、GENK は自分用の device communicator の準備が要るので、従来の流れの symmetric カーネルのスケジューラから起動されます。 まとめ staging の GENK は、Hopper 以降の GPU でビルドと環境変数で有効にすると NVLink、PCIe、ネットワークのどの経路でも同じカーネルが候補になり、EFA の複数ノードでは strong signal を提供する GIN Proxy の経路を使います。CFT を使う階層型カーネルは部品だけが公開コードにあり、New Enqueue Pipeline は枠組みが既定で無効のまま dev で進んでいます。

  3. DeepInfer Reads Like an Answer to DeepSeek’s Own 2025 Objections - * * On October 20, 2026, DeepSeek announced DeepInfer, the inference framework it says serves DeepSeek-V4.1-Flash in production, and published the code under Apache 2.0. Eighteen months earlier, the same company had explained in writing why it would not release its engine. As The New Stack quotes that post, the software was “impractical for public deployment without significant modifications.” Both statements can be true at once, and the space between them is where this release gets interesting. DeepInfer is a real production engine: kernels, a scheduler, a sampler, and multi-chip parallelism. It is also an offline inference release that leaves out the KV cache system, prefill and decode disaggregation, and load balancing across replicas. Those missing layers are the ones that bind most tightly to a specific cluster. This post reads the repository, its examples, and the first round of reporting, and it marks which claims are DeepSeek’s and which readings are mine. > Quick take: DeepInfer is most useful as a reference implementation and as a day-one path to V4.1-Flash on NVIDIA SM100 and Huawei Ascend 950. It is not a drop-in serving stack, DeepSeek’s speed figures have no independent verification yet, and the determinism features work on NVIDIA only. - * * What DeepSeek said in 2025 DeepSeek’s earlier open-source push went component by component. In late February 2025, its Open Source Week shipped one building block a day: FlashMLA, an MLA decoding kernel for Hopper GPUs; DeepEP, an expert-parallel communication library; and DeepGEMM, an FP8 GEMM library. The week also covered the EPLB expert-parallel load balancer, the DualPipe training schedule, and the 3FS file system. Inference code was the thin spot. For V3, the model card offered the DeepSeek-Infer demo, described as a “simple and lightweight demo” for FP8 and BF16, alongside community engines such as SGLang and LMDeploy for serving it. In April 2025 the same index gained a post on open-sourcing the inference engine. According to The New Stack’s account, DeepSeek had considered releasing the whole system and chose to contribute pieces to existing projects instead. Its reasons, in short: the engine had grown from an early vLLM version into a heavily customized system, a small research team would struggle to maintain another major open-source project, and the code was entangled with internal infrastructure. The entanglement point matters most for what follows. The post tied it specifically to cluster management tooling. DeepSeek also made a promise about hardware. It said it would synchronize inference engineering with partners ahead of future model launches, aiming for day-one availability across chip architectures. Keep that in mind for the Huawei section below. - * * What shipped on October 20 The repository supports one model, DeepSeek-V4.1-Flash, on two hardware families: NVIDIA SM100 GPUs and Huawei Ascend 950 NPUs. The default checkpoint is DeepSeek-V4.1-Flash-1017, the updated weights DeepSeek released days earlier. Two companion facts shape the picture. DeepSeek credits vLLM as the base: DeepInfer was originally built primarily on it, with inspiration from SGLang and TensorRT-LLM. And a second repository, deepseek-recipe, ships alongside. It handles how API requests become model inputs and how outputs become responses, in Rust and Python, so self-hosters can match the behavior of DeepSeek’s official API. The upstream loop DeepSeek described in 2025 is already visible. TNW reports that the vLLM project thanked DeepSeek and said it would keep improving its own V4.1-Flash support with ideas from DeepInfer. The repository had passed 8,000 stars by Tuesday afternoon, per the same report, and showed about 12,400 stars and 1,100 forks at the time of writing. !Mermaid Diagram - * * The scope is the argument Here is the boundary, drawn from the README’s own list of what a complete inference service still needs. !Mermaid Diagram The announcement called DeepInfer “fully open source.” The README is more careful. It describes offline inference with the core features needed for serving at scale, then lists three components it does not include: a KV cache system, VE/prefill/decode disaggregation (with the note that most of the required engine functionality is already implemented), and load balancing across data-parallel replicas for both prefill and decode. Set that against the entanglement objection. What the README leaves out is the layer that routes requests to replicas, decides where cached prefixes live, and splits phases across machines. Those parts depend on your network, your scheduler, and your traffic. The release boundary sits roughly where the coupling to infrastructure would be tightest. That is my reading, and DeepSeek has not said so. The New Stack makes a similar observation and points out that the company has not explained how it overcame the earlier difficulties. For planning, the line is simple. Offline batch inference, evals, and research on a cluster you control: DeepInfer is close to complete. A multi-tenant chat API with prefix caching and replica routing: budget significant engineering time for the layer above it. - * * Inside the engine The README’s feature list is easier to judge with the switches next to it. | Feature | What it does | How to turn it on | | --- | --- | --- | | Parallelism | Attention DP and balanced CP, plus MoE expert parallelism with EPLB | --ep, --dp, and --cp flags in the offline example | | Asynchronous scheduling | Overlaps CPU batch scheduling with device execution | On by default | | DSpark with confidence-scheduled verification | Decodes with draft tokens and uses confidence estimates to schedule verification | DEEPINFER_ENABLE_MTP_VARLEN=1; DEEPINFER_USE_NEXTN_DECODE sets max draft length (default 5) | | Decoder SWA bounded replay | Cuts decoder prefill work by replaying only a bounded suffix | DEEPINFER_YOCO_PREFILL_TRUNCATION_MODE=compact and DEEPINFER_YOCO_PREFILL_KEEP_TOKENS=140 | | Batch-invariant inference | Keeps results identical across batch compositions | DEEPINFER_BATCH_INVARIANT=1 (NVIDIA only) | | Deterministic sampling | Identical outputs for identical input tokens and sampling parameters | DEEPINFER_BATCH_INVARIANT=1 DEEPINFER_ENABLE_MTP_VARLEN=0 plus a fixed seq_seed (NVIDIA only) | | Structured outputs | Constrains generation to a regex, JSON schema, or EBNF grammar | so_args passed to SamplingParams | Read the last column twice. The DSpark recipe sets DEEPINFER_ENABLE_MTP_VARLEN=1, and the deterministic-sampling recipe sets the same variable to 0. If you need reproducible outputs for evals or regression tests, the two documented recipes pull in opposite directions. The README does not quantify the cost, so test before assuming they compose. Bounded replay exposes a model-specific constant. The README says the retained suffix must cover the sliding-window-attention window plus the maximum backtracking length, and it gives 140 tokens as the default for V4.1. Treat 140 as a V4.1 setting, not a universal one. Anyone adapting the engine to another model has a number to derive rather than copy. The kernel list is the 2025 strategy, assembled. FlashMLA, DeepGEMM, and DeepEP are the Open Source Week repositories. TileKernels, DeepSelect, and custom TileLang kernels in the tree join them. Read together, DeepInfer is where the formerly separate components meet a scheduler and a model runtime. - * * The vision encoder rides along V4.1-Flash accepts images, and the engine handles them in-process. With --prompt_mode image, the examples feed raw images to the engine directly, with the ViT and the LLM in the same engine. CPU preprocessing runs in asynchronous MultimodalProcessor worker processes, off the step critical path. That explains the odd “VE” in the list of missing components. VE is the vision encoder, and the examples benchmark it on its own. A sweep script loads only the VE-side weights, then times the GPU-side pad, ViT, downsample, and aligner path across image sizes and batch counts. Throughput is scaled by the number of LLM tokens each image produces, the same unit as the prefill curve, so the two are comparable. So “VE/prefill/decode disaggregation” is a three-stage split with the encoder as a separable stage. What the release leaves to you is the orchestration around it. The vision regression suite is refreshingly small: five inputs, made of two text-only samples, a single-image sample, a three-image sample, and a five-image four-shot sample. Every image comes from just two pictures, carrots and ribs. - * * Reading the benchmark charts without fooling yourself The README shows two Pareto plots: prefill (non-cached input throughput against latency) and decode (output throughput against per-user speed). DeepSeek measured them on 4 SM100 GPUs for prefill and 64 for decode, each within one scale-up domain, and points to run_sweep.sh for reproduction. TNW relays Bloomberg’s note that no one has independently benchmarked DeepInfer’s gains yet. The examples README documents the harness in unusual detail, and one line changes how you should read the decode curve. Decode throughput is computed like this: decode tokens/s/GPU = avg_SPS x decode_num_requests x (1 + nextn) / cp The docs call this full-acceptance accounting: every request is credited with 1 + nextn tokens per step, regardless of the true acceptance rate. With the defaults of 64 requests and a draft length of 5, one step counts as 384 tokens. Real speculative decoding rarely accepts every draft token, so a full-acceptance figure is a ceiling. The sweep script takes an acceptance-rate argument, and the docs’ own example sweeps a draft length of 3 and scales the decode plot by 0.75. Which scaling, if any, the published figure uses is not stated. Before comparing against vLLM or SGLang, check that setting. The methodology has strengths worth copying. The harness separates prefill from decode, drops intervals that collide with MoE load-balance statistics flushes, and runs sweeps with the profiler off because it perturbs timings. It also warns that profiler-traced step times can be inflated by nearly 50% at batch size 1 and must not be used to derive steps per second. Numerics are held to an exact standard. Perplexity baselines live in tests/models/offline_decode_ppl.json, keyed by platform and workload, and validation compares them sample by sample. A refresh_offline_decode_ppl.py script updates them once a numeric change is confirmed as expected, and the docs say to re-measure the short and long baselines on NVIDIA and Ascend separately after changing the vision samples. A --check_structured_output flag extends the same run to regex, JSON, and EBNF checks. If you plan to compare DeepInfer with another engine, hold these constant. The list is mine, built from what the harness documents: - Hardware and scale-up domain. Match the layout behind the published figures, or state how yours differs. - Workload shape. Harness defaults are 32,768 context tokens with 4,096 non-cached. The documented nightly profile configuration uses 128k context with YoCo clipping. - Draft length and token accounting. State your draft length, and whether you count full acceptance or measured acceptance. - Raw quantities. --result_jsonl appends the configuration plus window step count, token count, elapsed time, and avg_SPS, so you can recompute throughput under your own accounting. - One tag per curve. The sweep tooling blocks plotting when model, ep_size, --cp, context length, draft length, or redundant expert count differ within a tag. Borrow that discipline. - * * Nvidia and Huawei, side by side The hardware list is the most strategic line in the README. Next to NVIDIA’s SM100 parts, which The New Stack identifies as Blackwell data-center GPUs, sits Huawei’s Ascend 950 series, with CANN 9.2 as its prerequisite. Older NVIDIA architectures such as Hopper are absent. The New Stack places this inside a run of reporting. Bloomberg said in September that DeepSeek planned to deploy at least 160,000 Ascend 950DT chips at a new Inner Mongolia data center. Reuters later that month reported DeepSeek and Huawei collaborating on tools to make Ascend chips easier to program. TNW adds that DeepSeek published tooling for Huawei chips earlier in October as an alternative to CUDA. Parity is incomplete. Batch-invariant inference and deterministic sampling are NVIDIA only, and the published performance numbers all come from NVIDIA GPUs. The README gives no Ascend numbers. The examples do show Ascend taken seriously. They document debugging variables such as ASCEND_LAUNCH_BLOCKING=1, which runs operators synchronously so stack traces are readable, and, with the separate numeric baselines described earlier, that reads as a first-class target rather than an afterthought. This matches the 2025 promise of day-one cross-chip support, delivered for one model on two chip families. It is a narrow delivery of a broad commitment. TNW reports that DeepSeek says future models and improvements will land in the same repository. - * * Running it today The prerequisites are Linux, GCC 13 or newer, Python 3.12, and either CUDA 13 (NVIDIA) or CANN 9.2 (Ascend). Start from an empty Python 3.12 environment. export DEEPINFER_ACCELERATOR=nvidia # use "ascend" on Ascend ./build.sh # first run downloads DeepSeek-V4.1-Flash-1017 into the Hugging Face cache python examples/offline_inference.py --ep 8 The feature switches in the table above are environment variables, so export them in the same shell before launching. The offline example sets its layout with flags. The documented variants are --ep 8, --ep 2 --dp 8, and --ep 2 --cp 8. Set DEEPINFER_HF_MODEL_DIR to run from a local copy of the weights. The benchmark harness works differently, and the difference trips people up. There, ep_size equals WORLD_SIZE (the number of nodes) times the number of visible devices, and --cp must divide it. Redundant experts default to 32 through DEEPINFER_OVERRIDE_NUM_EXTRA_EXPERTS, but that value is only a lower bound: the engine rounds the total up so the expert count divides evenly by ep_size. The hardware requirement is the main gate: the README supports SM100 and Ascend 950 only. - * * Who should adopt it | If you are | Verdict | Why | | --- | --- | --- | | An inference-engine engineer | Read the code this week | A major lab’s account of what matters at scale, under Apache 2.0 | | A hosting provider on Blackwell or Ascend 950 | Pilot it | You get the kernels and parallelism, but you supply KV cache, disaggregation, and routing, and you must verify the speed claims yourself | | A team running offline batch jobs or evals on SM100 | Strong fit | Offline inference is what shipped, and batch invariance helps reproducibility on NVIDIA | | An app team calling a hosted API | Skip for now | Nothing in the release changes how you call a model | | A team on Hopper or older GPUs | Wait | The hardware is unsupported as released, so keep using vLLM or SGLang for now | - * * What to watch next Four signals will show how far DeepInfer travels beyond the announcement. - Independent benchmarks on identical hardware and identical token accounting, against vLLM and SGLang. - The missing layers. The README calls them required for a complete service. Whether DeepSeek will ship them is unannounced. - What lands upstream. vLLM said it would use ideas from DeepInfer. Watch for merged changes rather than statements. - Ascend parity for batch-invariant inference and deterministic sampling. The 2025 objections did not disappear. They moved to the edge of the release, where your own cluster begins. For anyone who builds or tunes inference engines, DeepInfer is a look at what a major lab says it runs in production. For teams that need a serving stack today, it is a release to watch rather than deploy. --- Published via ZyVOP — Write once in Markdown, auto-backup to GitHub, and syndicate to Dev.to, Medium & Hashnode in 1 click.

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

No packages found.

README badges

Embed a badge in your README or website.

  • deepseek-ai/DeepEP reached #1 in daily stars on gitwal · Feb 25, 2025
  • deepseek-ai/DeepEP reached #2 in weekly stars on gitwal · Week of Feb 24, 2025
  • deepseek-ai/DeepEP reached #1 in daily forks on gitwal · Feb 25, 2025
Live mentions · last 30 days
deepseek-ai/DeepEP mentions in the last 30 days