深入 DeepInfer:DeepSeek 的 V4.1-Flash 架構
DeepInfer 是 DeepSeek 的 V4.1-Flash 推理架構,而它最有趣的程式碼並不是某個 kernel,而是一連串排程與記憶體決策,讓大型 GPU 叢集不會彼此空等。以下帶你走一遍,並附上生產環境的注意事項。
DeepInfer 是 DeepSeek 為 V4.1-Flash 開源的推理架構。要讀得準,得先分開三層:模型、引擎、服務。模型是 V4.1-Flash;引擎是本頁的主題;服務則是 DeepSeek 保留的那一塊。
推理引擎到底在做什麼
訓練好的模型只是一堆權重。要把它服務出去,就得回答請求:讀取 prompt、執行模型、生成 token、回傳結果,並且同時服務許多使用者,而不浪費昂貴的硬件。
成本主要由兩個階段決定:
- Prefill 讀取 prompt 並建立 KV cache。它偏重運算,能平行處理大量 prompt token。
- Decode 一次生成一個 token。每一步都要讀 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,並且平衡兩種不同的工作負載。
DeepSeek 的生產數據:
| 階段 | 平行配置 | 原因 |
|---|---|---|
| Prefill | EP2–8 / DP2–8 | 用放得進 HBM 的最小 EP/DP;prefill 受運算限制。 |
| Decode | EP64–128 / DP64–128(Wide-EP) | 用可用的最大 EP/DP;decode 受記憶體流量限制。 |
| 視覺編碼器 | 每個實例一張 GPU | 模型很小;別浪費一張高階卡。 |
| TP / CP | 生產環境未使用 | 開源引擎的範例仍提供 CP;但生產描述不使用 TP/CP。 |
DeepSeek 把 64 張 prefill GPU 加 64 張 decode GPU 稱為最小的有效單位。1P + 1D 的配置可以部署,但建議的 decode 配置是 EP64 以上,因此小叢集看不到同樣的效率。
專家負載平衡:冗餘副本與定期重排
MoE 路由並不平均。有些專家很熱門,有些閒著。靜態分配會浪費 GPU。DeepSeek 的 EPLB(專家平行負載平衡)加入冗餘專家——熱門專家的副本——並依近期負載定期把專家重新指派到 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 是最慢的 rank 除以平均值。1.09 表示最慢的 GPU 比平均多做了約 9% 的工作。在 decode 的規模下,這是相當緊的數字;它也意味著最快的 GPU 仍要在屏障前等待。
moe_lb 是 1.074 / 1.045;中文知乎文章給的是 1.0320 / 1.0618。decode 的數字(1.090)兩邊一致。我們對 prefill 採區間,decode 採穩定值。DSpark:把驗證算力花在值得的地方
推測解碼用草稿模型先提出幾個 token,再一次驗證。如果草稿猜對了,就能用一次驗證的成本拿到多個 token;猜錯了就退回。
樸素版本會固定驗證一定數量的草稿。DSpark 的不同之處是可變長度驗證:信心頭預測每個草稿 token 的接受機率,排程器再挑出能讓有效吞吐量最大的前綴子集。
DeepSeek 也公開了 DeepSpec,一套 MIT 授權的程式庫,用於訓練與評估推測解碼的草稿模型。它涵蓋 DSpark、DFlash 與 Eagle3,與 DeepInfer 引擎分開。
DeepSeek 的生產量測:
| 指標 | 固定 5 | 動態長度 |
|---|---|---|
| 每步驗證的草稿 token 數 | 5.00 | 3.2–4.4 |
| 平均接受長度 | 3.29 | 3.20 |
| 生產運行點吞吐量(約 60 seqs/rank) | — | +4–7% |
| 96 seqs/rank 時的吞吐量 | — | +11% |
重點在解讀:驗證工作量少了約 30%,接受長度卻幾乎沒變。在高併發下淨收益為正。在每個 rank 16 條序列時,表格顯示反而是小幅損失(−1.5%)。這不是免費午餐,而是取決於負載的優化。
本次發佈的預設最大草稿長度是 5。不過公布的 decode 圖使用的是 nextn=3 fixed 與 75% 的單 token 接受率假設——那是量測配置,不是預設部署。
SWA 有界重放:讓失手變便宜,然後乾脆不存快取
滑動視窗注意力(SWA)只保留最近 token 的完整注意力。V4.1 使用 128 token 的視窗。若 SWA KV cache 缺失,精確復原的代價很高:每個解碼層的視窗都依賴下一層,因此要跨 20 個解碼層重建狀態,約需 2,560 次 token-層重放(20 × 128)。
SWA 有界重放刻意做近似:
- 只重放最後 128 個 token。
- 在重放起點截斷注意力視窗:位置 i 只注意
[max(s, i−127), i]。 - 接受近似的 SWA KV cache,重算成本有界且固定。
本次發佈的 V4.1 預設保留 140 token 的尾端(DEEPINFER_YOCO_PREFILL_KEEP_TOKENS=140)。多出的空間用來覆蓋視窗,加上推測解碼的回退。
這件事的意義不只是省算力:它讓「不持久化 SWA KV」成為理性選擇。因此 V4.1 的持久 KV cache 只存 global KV,不存 SWA KV,體積縮到約 V4 的八分之一。global KV 本身壓縮到每 token 約 890 bytes,約為 V4-Flash 的四分之一。
有界重放不是 bit-exact。DeepSeek 說品質損失可忽略。vLLM 在自己的實作中獨立測試過相同思路,於 GSM8K 與 GPQA 上回報的差距約在 1.5 個標準誤內——這說明思路合理,但不構成對 DeepInfer 特定程式碼的驗證。
非同步排程:別讓 GPU 等 CPU
一個 decode 步驟長這樣:
schedule(N) → forward(N) → sample(N) → post-process(N)
schedule 與 post-process 是 CPU 的工作。在 post-process(N) 之前,CPU 需要 GPU 傳回 sample(N) 的結果。這個同步點讓 GPU 在 CPU 處理結果、排下一批的空檔閒置。
DeepInfer 把兩者重疊:
GPU: forward(N) → sample(N)
CPU: schedule(N+1) → launch_forward(N+1) → post-process(N−1) → launch_sample(N+1)
這個想法並不新——DeepSeek 引用了 SGLang 與 NanoFlow——但實作是本次發佈的一部分,而且預設開啟。這正好說明,什麼樣的工作把 benchmark kernel 和服務引擎區分開來。
批次不變推理與確定性取樣
動態 batching 會改變浮點數累加的順序。同一個 prompt,可能因為當時同批的其他請求不同,而產生略微不同的 logits。對聊天而言,這通常看不出來;對 benchmark、稽核或重現 agent 執行,這就是問題。
DeepInfer 提供兩層控制:
- 批次不變推理(
DEEPINFER_BATCH_INVARIANT=1):在不同批次組成下,結果保持一致。 - 確定性取樣:相同輸入 token 與取樣參數會產生相同輸出。它需要批次不變模式、關閉 MTP 可變長度解碼(
DEEPINFER_ENABLE_MTP_VARLEN=0),以及固定的seq_seed。
本次發佈中,兩者都僅限 NVIDIA。它們不是宣傳亮點,卻是認真的評測團隊會注意到的東西。
結構化輸出:約束語法,而不是約束 prompt
結構化輸出把生成限制在 regex、JSON Schema 或 EBNF 語法內。DeepSeek 的生產設計會在一台獨立機器上把約束編譯成語法自動機,然後在每個 decode 步驟套用 token 遮罩。編譯與推理解耦,請求可以在進入引擎前先拿到編譯好的語法。
本次發佈的 API 是 SamplingParams(so_args={"schema_type": ..., "schema": ...})。離線範例也能用 --check_structured_output 執行 regex、JSON 與 EBNF 檢查,並確認正常的 EOS 結束。
這不是 DeepInfer 獨有——受限解碼是眾所周知的技術——但把它放進服務引擎內,對 agent 與抽取類工作負載很方便。
DeepSeek Recipe:「API 兼容」的另一半
推理引擎負責算出 token。API 服務還得:
- 接受 Chat Completions、Responses 與 Messages 請求;
- 套用模型的 prompt 格式,包括思考模式、工具與圖片;
- 把文字編碼成 token ID,同時不讓使用者文字注入特殊 token;
- 跨 chunk 邊界解析串流輸出;
- 把推理內容、工具呼叫與停止序列轉回協定回應。
deepseek-recipe 做的就是這些。它是獨立的 MIT 授權儲存庫:Rust 函式庫加 Python 綁定,另有範例伺服器。DeepSeek 說其處理邏輯與官方 API 對齊,因此第三方部署可以表現得像官方服務。
兩個細節值得留意:
- 特殊 token 注入防禦。 若使用者輸入
<|User|>或<|image|>,Recipe 會將它編碼成普通文字,而非控制 token。模型無法被誘導把使用者內容當成角色邊界。 - 分段平行分詞。 建立 prompt 時就已知道特殊 token 及其位置,因此其間的普通文字段落可以各自獨立編碼再串接。這能降低長上下文的 tokenization 延遲。
如果你把 DeepInfer 當服務堆疊來評估,Recipe 值得和引擎一樣多的注意力。引擎是昂貴的那一半;Recipe 是讓 API 用起來對的那一半。
新想法還是舊想法?
| 概念 | 狀態 | DeepSeek 加了什麼 |
|---|---|---|
| 推測解碼 | 既有技術 | DSpark 依信心排程的可變長度驗證 |
| 滑動視窗注意力 | 既有技術 | 有界重放 + 不持久化 SWA KV |
| 專家平行 | 既有技術 | 64–128 GPU 的 Wide-EP,加上生產級 EPLB 調校 |
| 連續批次 / 非同步排程 | 既有技術 | 完整、預設開啟的實作 |
| 結構化輸出 | 既有技術 | 整合進引擎,語法編譯獨立 |
| 批次不變 / 確定性推理 | 較少見 | 明確支援,條件寫明(僅 NVIDIA) |
| 專用 3FS 叢集上的 KV cache | DeepSeek 特有 | 100 PiB、3/7 天 TTL、跨機器 prefix 命中 |
| CED + SWA 重放協同設計 | DeepSeek 特有 | 模型架構與引擎一起調校 |
誠實的說法是:這些基礎技術大多不是 DeepSeek 發明的。貢獻在於整合——以及願意公開生產環境的調校參數。
生產設計 ≠ 開源程式碼
EPD、EPLB、KV cache 與負載平衡各節的內容,描述的都是 DeepSeek 在 Q&A 中記錄的生產系統。本次發佈不包含 KV cache 系統、VE/Prefill/Decode 分離,或資料平行負載平衡。讀生產設計有助於理解引擎,但它不是儲存庫的功能清單。
Q&A 真正給你的,是一張難得的地圖,說明程式碼背後的決策:為何 Wide-EP、為何 64+64、為何用 3FS、為何 TTL 是 3/7 天、為何有界重放、為何可變長度驗證。對其他實驗室的工程師來說,這張地圖是本次發佈最有價值的部分——即使程式碼只停在引擎邊界。
接著讀:如何讀那兩張圖、缺這些元件對部署的影響,或服務框架比較:vLLM、SGLang、TensorRT-LLM。