:大模型Prefill-Decode分離式推理架構與KV Cache跨節(jié)點傳輸)
27屆大模型面試準備六十九大模型Prefill-Decode分離式推理架構與KV Cache跨節(jié)點傳輸引言本篇是「工程實戰(zhàn)深化」系列的第 69 篇大模型線。上一篇六十八我們聊了長思維鏈與推理時計算擴展o1 類模型把大量算力壓在 prefill把整段思維鏈一次性前向和 decode逐 token 自回歸兩個階段。一旦思維鏈變長prefill 的耗時從「毫秒級」?jié)q到「秒級甚至十秒級」它和 decode 這對「性格完全不同」的階段被塞在同一個 GPU 池里就會互相拖累——這也是為什么今天的推理服務幾乎都走向Prefill-Decode 分離PD 分離 / disaggregated serving。本篇把 PD 分離講透為什么分離、池子怎么設計、KV Cache 在分離后為什么必須跨節(jié)點傳輸、傳輸協(xié)議怎么選、調(diào)度與前綴親和如何影響尾延遲最后給你一套可直接背的面試速答。建議和六十六推理調(diào)度、五十四推理成本、六十三前綴緩存一起看串起來就是一張完整的推理服務化地圖。1. 為什么必須分離兩種階段兩種資源畫像要理解 PD 分離先看清 prefill 和 decode 在硬件上的本質(zhì)差異。單請求視角 ┌──────────────────────────────────────────┐ │ Prefill │ │ 輸入: prompt 全部 token (N 個) │ │ 計算: 一次性全序列前向 (N×N 注意力) │ │ 特征: 計算密集 (compute-bound) │ │ batch 大、矩陣乘滿、GPU 利用率高 │ │ 耗時隨 N 線性~平方增長 │ ├──────────────────────────────────────────┤ │ Decode │ │ 輸入: 每步只 1 個 (或少數(shù)) 新 token │ │ 計算: 逐 token 前向受限于顯存帶寬 │ │ 特征: 訪存密集 (memory-bound) │ │ 大量小 kernel、GPU 算力閑置 │ │ 延遲敏感 (TTFT vs TBT/TPOT) │ └──────────────────────────────────────────┘兩者畫像沖突放在同一實例會出三類問題資源錯配prefill 想占滿算力做批量矩陣乘decode 想低延遲逐 token?;觳繒r decode 的小 kernel 打斷了 prefill 的大 kernel雙方都吃不滿。尾延遲塌方一個超長 prompt 的 prefill 搶占 GPU 幾十秒同卡上正在 decode 的請求 TBT每 token 延遲被拖成幾秒P99 爆掉。擴縮困難prefill 和 decode 的負載曲線完全不同prefill 取決于輸入長度分布decode 取決于并發(fā)與輸出長度合在一起無法獨立擴縮容。下表是單體部署 vs 分離部署的對照維度單體部署 (prefilldecode 同池)PD 分離部署資源利用prefill/decode 互相搶占各自池化算力吃滿TTFT首 token受長 prompt 與同卡 decode 干擾prefill 池獨立TTFT 穩(wěn)定TBT續(xù) token被長 prefill 拖尾decode 池不被 prefill 打擾擴縮容必須整體擴prefill/decode 分別擴KV Cache同卡共享零拷貝跨節(jié)點傳輸有開銷典型代表vLLM 早期、TGI 默認Mooncake、TensorRT-LLM PD、DistServe、SGLang 分離模式結(jié)論面試一句話PD 分離的核心動機是 prefill 計算密集、decode 訪存密集混部互相拖累尾延遲與利用率分離后可獨立擴縮并各自優(yōu)化。2. 分離架構總覽三個平面┌─────────────── 控制平面 (調(diào)度器) ───────────────┐ │ 接收請求 → 選 prefill 實例 → 等 KV 就緒 → 選 decode 實例 │ └───────────────────────────────────────────────────┘ 用戶請求 │ ▼ ┌─────────┐ KV Cache 傳輸 ┌─────────┐ │Prefill │ ─────(RDMA/NIXL)───? │ Decode │ ──? 流式輸出 │ Pool │ (prefill 完成后推送) │ Pool │ │ GPU×k │ │ GPU×m │ └─────────┘ └─────────┘ 大 batch 算力優(yōu)先 小 batch 延遲優(yōu)先 可搶占、可批量 continuous batching 前綴緩存命中優(yōu)先 KV 落本地顯存即開始 decode三個平面職責接入/網(wǎng)關做認證、限流、請求排隊呼應六十六、七十。調(diào)度器控制平面決定一個請求先去哪個 prefill 實例前綴親和prefill 完成后 KV 傳到哪個 decode 實例負載均衡。數(shù)據(jù)傳輸平面prefill 與 decode 之間的 KV Cache 搬運是分離架構的「命門」。3. Prefill Pool 設計要點prefill 是計算密集、對延遲相對不敏感只要 TTFT 在可接受區(qū)間所以它最該做的是把算力吃滿大 batch、高吞吐把多個請求的 prompt 拼成大 batch 一次前向矩陣乘效率最高??蓳屨汲L prompt 不應無限占卡調(diào)度器可對 prefill 任務做時間片搶占或按長度分級隊列。前綴緩存優(yōu)先相同 system prompt如固定人設、few-shot、RAG 檢索到的公共文檔的請求路由到同一 prefill 實例命中 prefix cache呼應六十三避免重復計算。Chunked Prefill超長 prompt 切成 chunk 分批前向避免單次 prefill 撐爆顯存或長時間獨占。注意 chunked prefill 會和 decode 的 continuous batching 爭搶這也是分離要解決的問題之一。# 偽代碼prefill 實例處理一批請求簡化defprefill_batch(requests):# requests: 同一 prefill 實例上的請求集合input_idspad_and_batch([r.prompt_idsforrinrequests])# 命中 prefix cache 的 prefix 段跳過計算六十三cached_len[prefix_cache_match(r)forrinrequests]# 僅對未緩存段做前向拼接已緩存 KVkvmodel.prefill(input_ids,skip_lencached_len)forr,kinzip(requests,kv):# 通知調(diào)度器本請求 KV 已就緒可發(fā)往 decodetransfer_engine.push(r.req_id,k)# 推送到目標 decode 實例scheduler.mark_prefill_done(r.req_id)return4. Decode Pool 設計要點decode 是訪存密集、對延遲極其敏感設計目標是低 TBT、高并發(fā)、不空轉(zhuǎn)Continuous Batching不等一個請求生成完再換 batch每出一個 token 就動態(tài)增刪序列呼應五十九/六十六。小步快跑每步只算 1 個新 token 的注意力 FFN受限于 HBM 帶寬而非算力。KV 落本地即開 decode從 prefill 拿到 KV 后decode 實例把 KV 搬進自己顯存立即開始自回歸不需要等完整響應。投機解碼可疊加decode 階段可接草稿模型加速呼應二十五與是否分離正交。5. KV Cache 跨節(jié)點傳輸分離架構的命門分離后prefill 算出的 KV 在 prefill 實例顯存里decode 在另一臺機。KV 不能共享顯存必須傳過去。KV 的體量很可觀單層 KV 2 × seq_len × num_kv_heads × head_dim × bytes。一個 7B 模型、seq4k、BF16KV 大約數(shù)百 MB 到 GB 級。傳輸設計直接決定端到端延遲。Prefill 實例顯存 傳輸平面 Decode 實例顯存 ┌─────────────┐ ┌─────────────────┐ ┌─────────────┐ │ KV layer0..L│ ─────? │ Transfer Engine │ ───? │ KV layer0..L│ │ (計算產(chǎn)出) │ RDMA │ - 按層/按塊推送 │ RDMA │ (decode 消費)│ └─────────────┘ │ - 零拷貝注冊 │ └─────────────┘ │ - 異步流水線 │ └─────────────────┘關鍵設計決策傳輸時機prefill 一算完某一層或整段就異步推送而不是等全部算完再傳形成「計算-傳輸」流水線掩蓋傳輸延遲。傳輸粒度按層layer-by-layer或按 KV blockPagedAttention 的 block 單位呼應三十六/五十九推送decode 收到 block 即可提前開始對應層的解碼。傳輸網(wǎng)絡同機走 NVLink/PCIe跨機走RDMARoCE/InfiniBand避免走 CPU 和 TCP 協(xié)議棧延遲從毫秒級降到數(shù)十微秒。零拷貝用注冊內(nèi)存registered memory / GPUDirect RDMA讓網(wǎng)卡直接讀寫 GPU 顯存避免 CPU 中轉(zhuǎn)。傳輸協(xié)議抽象主流做法是把傳輸從引擎解耦成獨立 Transfer Engine如Mooncake Transfer Engine基于 RDMA支持 KV 跨節(jié)點直傳、NIXLNVIDIA 的異構內(nèi)存?zhèn)鬏敵橄髮咏y(tǒng)一 CPU/GPU/網(wǎng)絡。這讓上層調(diào)度器不用關心底層是 RDMA 還是 PCIe。# 偽代碼基于 Transfer Engine 的 KV 推送對齊 Mooncake/NIXL 思路classKVTransferEngine:def__init__(self,backendrdma):self.backendbackend# rdma / nvlink / tcpdefpush(self,req_id,kv_layers,dst_decode_rank):# kv_layers: 按層切好的張量列表forlayerinkv_layers:# 注冊顯存并異步 RDMA 寫不阻塞 prefill 后續(xù)計算self._async_write(srclayer.gpu_ptr,dstdecode_kv_slot(dst_decode_rank,req_id),cblambda:scheduler.on_kv_arrived(req_id,layer.idx))# 全部層抵達后調(diào)度器把請求交給 decode 實例面試常問「KV 傳輸會不會成為瓶頸」答會所以工程上靠 RDMA 按層異步流水 零拷貝把傳輸和 prefill 計算重疊傳輸延遲被掩蓋若網(wǎng)絡帶寬不足如只有 TCP分離反而可能因為傳輸開銷變慢務必評估網(wǎng)絡。6. 調(diào)度與前綴親和決定尾延遲的兩件事分離后調(diào)度器要回答兩個問題prefill 去哪decode 去哪Prefill 路由 前綴親和把共享同一段 system prompt / 公共前綴的請求路由到同一 prefill 實例最大化 prefix cache 命中呼應六十三/七十。這是降本和保 TTFT 的關鍵。Decode 路由 負載均衡按各 decode 實例的 inflight 序列數(shù)、預估剩余 KV 顯存選最空的實例避免某卡被長輸出拖垮。KV 親和進階若 decode 實例已緩存了某請求的歷史 KV多輪對話續(xù)寫優(yōu)先把請求路由回持有該 KV 的 decode 實例省去重傳。請求 ──┬─ prefix hash ──? Prefill 實例 (命中前綴緩存, 跳過重復計算) │ └─ 負載評估 ─────? Decode 實例 (KV 到達后最低負載者)7. 故障與一致性分離引入跨節(jié)點依賴要處理Prefill 失敗調(diào)度器把請求重排到另一個 prefill 實例重算prefix cache 可復用部分段。KV 傳輸中斷decode 側(cè)未收齊 KV觸發(fā)重傳或回退到「prefill 與 decode 同實例」的單體兜底路徑。Decode 實例崩潰該實例上的在途請求狀態(tài)已生成的 token、KV 槽位需可恢復——靠檢查點/狀態(tài)外置呼應二十二/六十三重路由到新 decode 實例續(xù) decode。Partial KV按層傳輸時 decode 已拿到前幾層 KV若傳輸斷要么丟棄重來要么用已到層做「降級解碼」工程上通常丟棄重傳簡單可靠。8. 生產(chǎn)落地 checklist網(wǎng)絡確認有 RDMA/RoCE否則分離收益大打折扣。監(jiān)控分別監(jiān)控 prefill 池的 TTFT 分布、decode 池的 TBT/P99、KV 傳輸帶寬與重傳率。熔斷KV 傳輸失敗率超閾值時自動回退單體模式呼應七十。容量prefill 與 decode 配比按流量畫像調(diào)長輸入多則多 prefill GPU。壓測用真實長度分布壓測別用固定長度 prompt會掩蓋 TTFT 長尾。面試速答為什么要 PD 分離prefill 計算密集、decode 訪存密集混部互相搶占導致尾延遲塌方、利用率低分離后獨立擴縮、各自優(yōu)化。KV 為什么要跨節(jié)點傳分離后 prefill 與 decode 在不同實例KV 不共享顯存必須傳到 decode 才能續(xù)解碼。怎么降低傳輸開銷RDMA 按層/按塊異步流水 GPUDirect 零拷貝 與 prefill 計算重疊。prefix cache 在分離下怎么用prefill 路由按前綴親和把同前綴請求送同一 prefill 實例命中緩存省錢又穩(wěn) TTFT。沒有 RDMA 能不能分離能但收益有限TCP 上傳輸開銷可能抵消分離收益需實測。故障怎么兜底prefill 重排重算、KV 傳輸失敗回退單體、decode 崩潰靠狀態(tài)外置重路由續(xù) decode。高頻追問清單PD 分離和 chunked prefill 是什么關系能否只做 chunked 不做分離chunked prefill 解決單次 prefill 占卡分離解決兩階段資源畫像沖突是正交的兩層優(yōu)化可單獨做KV 傳輸按層推和按 block 推各有什么取舍按層簡單、decode 可逐層解按 block 更貼合 PagedAttention、支持增量與復用多輪對話場景下decode 實例怎么復用上一輪 KVKV 親和路由 decode 側(cè) KV 槽位保留/外置Mooncake 和 NIXL 的區(qū)別是什么Mooncake 偏完整 Transfer Engine 實現(xiàn)NIXL 偏統(tǒng)一傳輸抽象層可被視為底層分離后怎么保證 decode 不被「超長輸出」請求餓死decode 池按序列數(shù)/顯存負載均衡 輸出長度預估 搶占prefill 池該不該也做 continuous batchingprefill 本身是批量前向continuous batching 主要是 decode 概念prefill 用 chunked 大 batch 即可