ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

27届大模型面试准备(六十九):大模型Prefill-Decode分离式推理架构与KV Cache跨节点传输

27届大模型面试准备(六十九):大模型Prefill-Decode分离式推理架构与KV Cache跨节点传输 27届大模型面试准备六十九大模型Prefill-Decode分离式推理架构与KV Cache跨节点传输引言本篇是「工程实战深化」系列的第 69 篇大模型线。上一篇六十八我们聊了长思维链与推理时计算扩展o1 类模型把大量算力压在 prefill把整段思维链一次性前向和 decode逐 token 自回归两个阶段。一旦思维链变长prefill 的耗时从「毫秒级」涨到「秒级甚至十秒级」它和 decode 这对「性格完全不同」的阶段被塞在同一个 GPU 池里就会互相拖累——这也是为什么今天的推理服务几乎都走向Prefill-Decode 分离PD 分离 / disaggregated serving。本篇把 PD 分离讲透为什么分离、池子怎么设计、KV Cache 在分离后为什么必须跨节点传输、传输协议怎么选、调度与前缀亲和如何影响尾延迟最后给你一套可直接背的面试速答。建议和六十六推理调度、五十四推理成本、六十三前缀缓存一起看串起来就是一张完整的推理服务化地图。1. 为什么必须分离两种阶段两种资源画像要理解 PD 分离先看清 prefill 和 decode 在硬件上的本质差异。单请求视角 ┌──────────────────────────────────────────┐ │ Prefill │ │ 输入: prompt 全部 token (N 个) │ │ 计算: 一次性全序列前向 (N×N 注意力) │ │ 特征: 计算密集 (compute-bound) │ │ batch 大、矩阵乘满、GPU 利用率高 │ │ 耗时随 N 线性~平方增长 │ ├──────────────────────────────────────────┤ │ Decode │ │ 输入: 每步只 1 个 (或少数) 新 token │ │ 计算: 逐 token 前向受限于显存带宽 │ │ 特征: 访存密集 (memory-bound) │ │ 大量小 kernel、GPU 算力闲置 │ │ 延迟敏感 (TTFT vs TBT/TPOT) │ └──────────────────────────────────────────┘两者画像冲突放在同一实例会出三类问题资源错配prefill 想占满算力做批量矩阵乘decode 想低延迟逐 token。混部时 decode 的小 kernel 打断了 prefill 的大 kernel双方都吃不满。尾延迟塌方一个超长 prompt 的 prefill 抢占 GPU 几十秒同卡上正在 decode 的请求 TBT每 token 延迟被拖成几秒P99 爆掉。扩缩困难prefill 和 decode 的负载曲线完全不同prefill 取决于输入长度分布decode 取决于并发与输出长度合在一起无法独立扩缩容。下表是单体部署 vs 分离部署的对照维度单体部署 (prefilldecode 同池)PD 分离部署资源利用prefill/decode 互相抢占各自池化算力吃满TTFT首 token受长 prompt 与同卡 decode 干扰prefill 池独立TTFT 稳定TBT续 token被长 prefill 拖尾decode 池不被 prefill 打扰扩缩容必须整体扩prefill/decode 分别扩KV Cache同卡共享零拷贝跨节点传输有开销典型代表vLLM 早期、TGI 默认Mooncake、TensorRT-LLM PD、DistServe、SGLang 分离模式结论面试一句话PD 分离的核心动机是 prefill 计算密集、decode 访存密集混部互相拖累尾延迟与利用率分离后可独立扩缩并各自优化。2. 分离架构总览三个平面┌─────────────── 控制平面 (调度器) ───────────────┐ │ 接收请求 → 选 prefill 实例 → 等 KV 就绪 → 选 decode 实例 │ └───────────────────────────────────────────────────┘ 用户请求 │ ▼ ┌─────────┐ KV Cache 传输 ┌─────────┐ │Prefill │ ─────(RDMA/NIXL)───▶ │ Decode │ ──▶ 流式输出 │ Pool │ (prefill 完成后推送) │ Pool │ │ GPU×k │ │ GPU×m │ └─────────┘ └─────────┘ 大 batch 算力优先 小 batch 延迟优先 可抢占、可批量 continuous batching 前缀缓存命中优先 KV 落本地显存即开始 decode三个平面职责接入/网关做认证、限流、请求排队呼应六十六、七十。调度器控制平面决定一个请求先去哪个 prefill 实例前缀亲和prefill 完成后 KV 传到哪个 decode 实例负载均衡。数据传输平面prefill 与 decode 之间的 KV Cache 搬运是分离架构的「命门」。3. Prefill Pool 设计要点prefill 是计算密集、对延迟相对不敏感只要 TTFT 在可接受区间所以它最该做的是把算力吃满大 batch、高吞吐把多个请求的 prompt 拼成大 batch 一次前向矩阵乘效率最高。可抢占超长 prompt 不应无限占卡调度器可对 prefill 任务做时间片抢占或按长度分级队列。前缀缓存优先相同 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):# 通知调度器本请求 KV 已就绪可发往 decodetransfer_engine.push(r.req_id,k)# 推送到目标 decode 实例scheduler.mark_prefill_done(r.req_id)return4. Decode Pool 设计要点decode 是访存密集、对延迟极其敏感设计目标是低 TBT、高并发、不空转Continuous Batching不等一个请求生成完再换 batch每出一个 token 就动态增删序列呼应五十九/六十六。小步快跑每步只算 1 个新 token 的注意力 FFN受限于 HBM 带宽而非算力。KV 落本地即开 decode从 prefill 拿到 KV 后decode 实例把 KV 搬进自己显存立即开始自回归不需要等完整响应。投机解码可叠加decode 阶段可接草稿模型加速呼应二十五与是否分离正交。5. KV Cache 跨节点传输分离架构的命门分离后prefill 算出的 KV 在 prefill 实例显存里decode 在另一台机。KV 不能共享显存必须传过去。KV 的体量很可观单层 KV 2 × seq_len × num_kv_heads × head_dim × bytes。一个 7B 模型、seq4k、BF16KV 大约数百 MB 到 GB 级。传输设计直接决定端到端延迟。Prefill 实例显存 传输平面 Decode 实例显存 ┌─────────────┐ ┌─────────────────┐ ┌─────────────┐ │ KV layer0..L│ ─────▶ │ Transfer Engine │ ───▶ │ KV layer0..L│ │ (计算产出) │ RDMA │ - 按层/按块推送 │ RDMA │ (decode 消费)│ └─────────────┘ │ - 零拷贝注册 │ └─────────────┘ │ - 异步流水线 │ └─────────────────┘关键设计决策传输时机prefill 一算完某一层或整段就异步推送而不是等全部算完再传形成「计算-传输」流水线掩盖传输延迟。传输粒度按层layer-by-layer或按 KV blockPagedAttention 的 block 单位呼应三十六/五十九推送decode 收到 block 即可提前开始对应层的解码。传输网络同机走 NVLink/PCIe跨机走RDMARoCE/InfiniBand避免走 CPU 和 TCP 协议栈延迟从毫秒级降到数十微秒。零拷贝用注册内存registered memory / GPUDirect RDMA让网卡直接读写 GPU 显存避免 CPU 中转。传输协议抽象主流做法是把传输从引擎解耦成独立 Transfer Engine如Mooncake Transfer Engine基于 RDMA支持 KV 跨节点直传、NIXLNVIDIA 的异构内存传输抽象层统一 CPU/GPU/网络。这让上层调度器不用关心底层是 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 后续计算self._async_write(srclayer.gpu_ptr,dstdecode_kv_slot(dst_decode_rank,req_id),cblambda:scheduler.on_kv_arrived(req_id,layer.idx))# 全部层抵达后调度器把请求交给 decode 实例面试常问「KV 传输会不会成为瓶颈」答会所以工程上靠 RDMA 按层异步流水 零拷贝把传输和 prefill 计算重叠传输延迟被掩盖若网络带宽不足如只有 TCP分离反而可能因为传输开销变慢务必评估网络。6. 调度与前缀亲和决定尾延迟的两件事分离后调度器要回答两个问题prefill 去哪decode 去哪Prefill 路由 前缀亲和把共享同一段 system prompt / 公共前缀的请求路由到同一 prefill 实例最大化 prefix cache 命中呼应六十三/七十。这是降本和保 TTFT 的关键。Decode 路由 负载均衡按各 decode 实例的 inflight 序列数、预估剩余 KV 显存选最空的实例避免某卡被长输出拖垮。KV 亲和进阶若 decode 实例已缓存了某请求的历史 KV多轮对话续写优先把请求路由回持有该 KV 的 decode 实例省去重传。请求 ──┬─ prefix hash ──▶ Prefill 实例 (命中前缀缓存, 跳过重复计算) │ └─ 负载评估 ─────▶ Decode 实例 (KV 到达后最低负载者)7. 故障与一致性分离引入跨节点依赖要处理Prefill 失败调度器把请求重排到另一个 prefill 实例重算prefix cache 可复用部分段。KV 传输中断decode 侧未收齐 KV触发重传或回退到「prefill 与 decode 同实例」的单体兜底路径。Decode 实例崩溃该实例上的在途请求状态已生成的 token、KV 槽位需可恢复——靠检查点/状态外置呼应二十二/六十三重路由到新 decode 实例续 decode。Partial KV按层传输时 decode 已拿到前几层 KV若传输断要么丢弃重来要么用已到层做「降级解码」工程上通常丢弃重传简单可靠。8. 生产落地 checklist网络确认有 RDMA/RoCE否则分离收益大打折扣。监控分别监控 prefill 池的 TTFT 分布、decode 池的 TBT/P99、KV 传输带宽与重传率。熔断KV 传输失败率超阈值时自动回退单体模式呼应七十。容量prefill 与 decode 配比按流量画像调长输入多则多 prefill GPU。压测用真实长度分布压测别用固定长度 prompt会掩盖 TTFT 长尾。面试速答为什么要 PD 分离prefill 计算密集、decode 访存密集混部互相抢占导致尾延迟塌方、利用率低分离后独立扩缩、各自优化。KV 为什么要跨节点传分离后 prefill 与 decode 在不同实例KV 不共享显存必须传到 decode 才能续解码。怎么降低传输开销RDMA 按层/按块异步流水 GPUDirect 零拷贝 与 prefill 计算重叠。prefix cache 在分离下怎么用prefill 路由按前缀亲和把同前缀请求送同一 prefill 实例命中缓存省钱又稳 TTFT。没有 RDMA 能不能分离能但收益有限TCP 上传输开销可能抵消分离收益需实测。故障怎么兜底prefill 重排重算、KV 传输失败回退单体、decode 崩溃靠状态外置重路由续 decode。高频追问清单PD 分离和 chunked prefill 是什么关系能否只做 chunked 不做分离chunked prefill 解决单次 prefill 占卡分离解决两阶段资源画像冲突是正交的两层优化可单独做KV 传输按层推和按 block 推各有什么取舍按层简单、decode 可逐层解按 block 更贴合 PagedAttention、支持增量与复用多轮对话场景下decode 实例怎么复用上一轮 KVKV 亲和路由 decode 侧 KV 槽位保留/外置Mooncake 和 NIXL 的区别是什么Mooncake 偏完整 Transfer Engine 实现NIXL 偏统一传输抽象层可被视为底层分离后怎么保证 decode 不被「超长输出」请求饿死decode 池按序列数/显存负载均衡 输出长度预估 抢占prefill 池该不该也做 continuous batchingprefill 本身是批量前向continuous batching 主要是 decode 概念prefill 用 chunked 大 batch 即可
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表