LLM 推理部署优化KV Cache、前缀缓存与推测解码的工程组合为什么模型能跑不等于服务能用大模型真正进入生产环境以后最容易被低估的问题不是模型能不能跑起来而是每生成一个 Token 到底要花多少钱、要等多久。实验环境中单次请求跑得快、显存占得满并不意味着线上服务具有好的经济性。生产环境面对的是持续到来的并发请求、长度差异巨大的 Prompt、不断增长的 KV Cache以及首字延迟TTFT、逐字延迟TPOT、吞吐量和显存利用率之间复杂的权衡。尤其对于长上下文和高并发场景模型权重本身反而不一定是第一瓶颈。随着请求数量和上下文长度增长KV Cache 会迅速占据大量 GPU 显存并进一步限制批大小、并发数和整体吞吐。因此推理优化不能简单理解为把模型从 FP16 换成 INT4真正有效的优化来自一个完整推理栈的协同量化、PagedAttention、KV Cache 管理、连续批处理、前缀缓存、内核优化、并发调度、硬件利用率优化。先理解一个事实LLM 推理为什么昂贵Transformer 的自回归生成过程分为两个阶段。Prefill预填充负责处理用户提交的 Prompt——假设系统提示词 200 token、用户上下文 5000 token、问题 200 token总共 5400 token 需要一次性并行计算这个阶段是计算密集型的。Decode解码阶段则完全不同——假设要生成 500 token每一步生成下一个 token 都依赖之前已经生成的内容是典型的自回归过程。KV Cache 的核心价值就在这里已经计算过的 Key 和 Value 不需要每个 Decode 步骤重新计算。这正是 KV Cache 成为现代 LLM 推理系统核心资源的原因——但同时它也是显存消耗的大户。KV Cache 为什么特别吃显存假设一个模型有 32 层、8 个 KV 头、每头维度 128、FP16 精度那么每个 token 的 KV Cache 大约是 32×8×128×2K 和 V×2字节数≈ 128KB。一个请求上下文达到 8192 token就需要约 1GB 的 KV Cache。如果同时有 16 个请求理论上就需要接近 16GB——所以在长上下文、高并发服务中真正限制并发能力的往往不是模型权重而是 KV Cache。现代模型大量使用 GQA分组查询注意力或 MQA多查询注意力来缓解这个问题。以 Query Heads 32、KV Heads 8 为例KV Cache 的头数不是 32 而是 8理论上可以把 KV Cache 的这部分降低到 25%。这也是 GQA 对推理系统非常重要的原因——选模型时KV Head 数量是一个值得关注的推理成本指标。PagedAttention把 KV Cache 像虚拟内存一样管理最早的推理实现为每个请求分配连续显存问题是请求长度不固定——如果按最大长度预分配产生大量浪费动态扩容又容易产生显存碎片。vLLM 的 PagedAttention 借鉴操作系统虚拟内存的分页机制把 KV Cache 切成多个固定大小的块Block通过块表Block Table建立逻辑块到物理块的映射。逻辑上连续、物理上离散请求需要多少块就分配多少请求结束立即释放供其他请求复用。这一机制把显存碎片显著降低让 GPU 显存更充分地服务于真实 token。Continuous Batching不要等待整个 Batch 结束传统静态批处理按最长请求同步执行短请求被迫等待GPU 计算资源大量浪费。连续批处理Continuous Batching把请求生命周期拆开某个请求完成后立即退出 batch新请求立即进入GPU 在每一个迭代中都可以尽可能装载更多可执行请求。配合 PagedAttention 的抢占式调度长请求可以被挂起并恢复不会阻塞短请求。生产调优时要注意不要盲目追求最大 batch。batch 增大通常意味着吞吐上升、显存占用上升、排队延迟上升、首字延迟可能上升。真正应该关注的是每迭代处理的 token 数max-num-batched-tokens而不是并发请求数max-num-seqs两者要联合调节。Prefix Caching重复 Prompt 不要重复计算很多企业应用存在高度重复的 Prompt——系统提示词、知识库规则、工具定义、Agent 指令前面几千 token 可能完全相同。如果每次请求都重新 Prefill这是明显的浪费。前缀缓存Prefix Caching的思想是第一次请求计算前缀并保存 KV后续请求匹配到相同前缀时直接复用 KV只计算新增内容。效果是首字延迟下降、GPU 计算减少、成本下降。对聊天机器人、Agent、RAG、企业知识库这类固定系统提示词和大量工具定义的场景尤其有效。落地时要注意缓存命中率如果前缀里混了时间戳、用户 ID 这类每次变化的字段缓存永远命中不了等于没开。Chunked Prefill解决长 Prompt 阻塞 Decode一个典型问题当前有 100 个 Decode 请求突然来了一个 10 万 token 的 Prompt。如果直接完整 PrefillGPU 被长时间占用Decode 请求全部等待用户感知延迟暴涨。Chunked Prefill 把长 Prompt 拆成多个块让 Prefill 和 Decode 合理地共享 GPU 计算资源——每个迭代既处理部分 Decode又处理一个 Prefill 块。这解决的是吞吐与交互延迟之间的调度问题。所以生产系统不能只看 tokens/s还必须同时观察 TTFT、ITL/TPOT、P99 延迟、排队时间和吞吐量。量化降低模型权重成本如果模型采用 BF16每参数 2 字节一个 70B 模型的权重理论存储约 140GB。用 INT4 量化后降到约 35GB——同样的 GPU 集群可以运行更大的模型或者运行更多副本。常见量化方案包括 FP8、INT8、INT4、GPTQ、AWQ。但一个反直觉的事实是不能简单认为 INT4 一定比 FP8 快。量化影响的不只是显存还涉及内存带宽、计算吞吐、内核效率、反量化开销、Tensor Core 利用率、精度。FP8 在现代 NVIDIA GPU 上有成熟的硬件支持某些 INT4 格式虽然更省显存但如果对应内核不够高效最终吞吐不一定更好。量化选型应该通过实际 Benchmark 决定而不是根据位宽数字大小决定。推测解码用小模型换大模型的延迟推测解码Speculative Decoding采用 Draft-Target 范式一个小模型Draft快速自回归生成 k 个候选 token大模型Target一次前向并行验证这些候选——接受的 token 直接输出被拒绝的从分歧点重新生成。由于大模型一次前向验证多个 token而小模型生成速度快整体解码速度可以提升 2~3 倍。生产落地时要注意监控接受率Acceptance Rate——它决定推测解码的实际收益。接受率低比如小模型和大模型风格差异大时推测解码可能不如直接解码。一般建议小模型选择与大模型同源或同族的较小版本接受率会明显更高。完整优化路径与监控生产部署建议从一个保守配置开始然后根据压测结果逐步调整。典型调优路径固定模型、固定 Prompt、固定输出长度然后测试不同并发观察 TTFT/TPOT再联合调整 max-num-seqs 和 max-num-batched-tokens。显存利用率不要一上来就顶到 0.98——GPU 显存里除了模型权重还有 KV Cache、CUDA 运行时、临时缓冲、激活值、内核工作区压得过满会出现难以排查的偶发 OOM。更合理的方法是从 0.85 到 0.90 到 0.92 逐级压测。监控层面集成 Prometheus 记录 KV 缓存使用率、运行中请求数、批 token 数、吞吐等指标便于自动扩缩容和预警。有一句话值得刻在监控面板上生产系统不能只看单点指标吞吐、延迟、成本三者必须放在一起看——牺牲任何一方换来的优化最终都要加倍还回去。