<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>性能 on lategege 的技术博客</title><link>https://lategege.com/tags/%E6%80%A7%E8%83%BD/</link><description>Recent content in 性能 on lategege 的技术博客</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sun, 22 Mar 2026 02:10:00 +0800</lastBuildDate><atom:link href="https://lategege.com/tags/%E6%80%A7%E8%83%BD/index.xml" rel="self" type="application/rss+xml"/><item><title>LLM 推理性能优化路线图：从瓶颈定位到 KV Cache、连续批处理与吞吐/延迟权衡</title><link>https://lategege.com/p/llm-inference-performance-roadmap/</link><pubDate>Sun, 22 Mar 2026 02:10:00 +0800</pubDate><guid>https://lategege.com/p/llm-inference-performance-roadmap/</guid><description>&lt;p&gt;把 LLM 服务真正跑起来后，你会很快发现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“模型很强”不等于“服务好用”&lt;/li&gt;
&lt;li&gt;性能问题不是一个点，而是一条链路：&lt;strong&gt;请求 → 编排 → 推理 → 解码 → 传输&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这篇文章给一套我认为实用的推理优化路线图：先定位瓶颈，再按收益/风险排序做改动。重点讲清楚三个常见核心点：&lt;strong&gt;KV Cache、连续批处理（continuous batching）、吞吐与延迟的权衡&lt;/strong&gt;。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;说明：以下讨论以 Decoder-only LLM（GPT 类）为主。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="1-先把指标做对不然你永远在感觉优化"&gt;1. 先把指标做对：不然你永远在“感觉优化”
&lt;/h2&gt;&lt;p&gt;推理服务至少要同时看两类指标：&lt;/p&gt;
&lt;h3 id="11-用户体验类latency"&gt;1.1 用户体验类（Latency）
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TTFT&lt;/strong&gt;（Time To First Token）：从收到请求到吐出第一个 token 的时间&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TPOT&lt;/strong&gt;（Time Per Output Token）：后续每个 token 的平均时间&lt;/li&gt;
&lt;li&gt;P50/P95/P99（尤其看 P95）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TTFT 决定“有没有卡住”，TPOT 决定“输出快不快”。&lt;/p&gt;
&lt;h3 id="12-资源效率类throughputcost"&gt;1.2 资源效率类（Throughput/Cost）
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;tokens/s（整体吞吐）&lt;/li&gt;
&lt;li&gt;GPU 利用率（SM occupancy 只是其中之一）&lt;/li&gt;
&lt;li&gt;显存占用（KV cache 往往是大头）&lt;/li&gt;
&lt;li&gt;单请求平均成本（按 token 计费更贴近现实）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;一个常见误区&lt;/strong&gt;：只盯 tokens/s，然后为了吞吐把 batch 拉很大，结果 TTFT 飙升，产品体验崩掉。&lt;/p&gt;
&lt;h2 id="2-理解两个阶段prefill-与-decode"&gt;2. 理解两个阶段：Prefill 与 Decode
&lt;/h2&gt;&lt;p&gt;LLM 推理可以粗略分成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prefill&lt;/strong&gt;：把 prompt 全部喂进去，计算每层 attention 的 K/V 并写入 KV cache&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decode&lt;/strong&gt;：每步只生成 1 个 token（或少量 token），每步读取 KV cache 做 attention&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;性能瓶颈往往在：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prefill 阶段：矩阵乘、attention 计算量大，吞吐与并行相关&lt;/li&gt;
&lt;li&gt;Decode 阶段：每步都要读 KV cache，常被&lt;strong&gt;显存带宽/访问模式&lt;/strong&gt;限制&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此优化也要分开看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;长 prompt&lt;/strong&gt;（RAG、工具调用）→ Prefill 压力更大&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长输出&lt;/strong&gt;（写作、代码生成）→ Decode 压力更大&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3-kv-cache为什么它是显存杀手也是性能命门"&gt;3. KV Cache：为什么它是显存杀手，也是性能命门
&lt;/h2&gt;&lt;h3 id="31-kv-cache-是什么"&gt;3.1 KV cache 是什么
&lt;/h3&gt;&lt;p&gt;对每一层 self-attention，你都要保存历史 token 的 Key/Value，后续解码才能复用。&lt;/p&gt;
&lt;p&gt;因此 KV cache 大小近似与以下因素线性相关：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;batch size&lt;/li&gt;
&lt;li&gt;context length（已处理 token 数）&lt;/li&gt;
&lt;li&gt;layer 数&lt;/li&gt;
&lt;li&gt;hidden size / head 数&lt;/li&gt;
&lt;li&gt;dtype（FP16/BF16/FP8/INT8 等）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="32-你会遇到的典型问题"&gt;3.2 你会遇到的典型问题
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;显存 OOM&lt;/strong&gt;：并发上来后突然炸&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;碎片化&lt;/strong&gt;：请求长短不一，cache 分配释放频繁，显存利用率下降&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;带宽瓶颈&lt;/strong&gt;：decode 阶段每步都要从显存读取大量 KV&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="33-工程策略按常见收益排序"&gt;3.3 工程策略（按常见收益排序）
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;限制最大上下文&lt;/strong&gt;：最粗暴但最有效&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;给产品一个“最大输入长度”的硬上限&lt;/li&gt;
&lt;li&gt;对 RAG：先做“检索截断 + 摘要压缩”，而不是直接堆 context&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;KV cache 量化/压缩（有风险，需验证）&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;目标：用更低精度存 KV，省显存/带宽&lt;/li&gt;
&lt;li&gt;风险：质量回退（尤其在长上下文）&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;strong&gt;更合理的 KV 分配策略（解决碎片）&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;思路：不要为每个请求随意 malloc/free，而是做“块化管理”&lt;/li&gt;
&lt;li&gt;这也是很多推理引擎会重点优化的点&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="4-连续批处理continuous-batching吞吐提升的关键"&gt;4. 连续批处理（Continuous Batching）：吞吐提升的关键
&lt;/h2&gt;&lt;h3 id="41-静态-batching-的问题"&gt;4.1 静态 batching 的问题
&lt;/h3&gt;&lt;p&gt;传统 batching：等凑够一批再跑。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对吞吐好&lt;/li&gt;
&lt;li&gt;对延迟差（TTFT 会因为排队变长）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="42-连续-batching-的核心思想"&gt;4.2 连续 batching 的核心思想
&lt;/h3&gt;&lt;p&gt;在 decode 的每一步，把“当前可执行的请求”动态拼成 batch。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新请求在 prefill 完成后可以插入 decode batch&lt;/li&gt;
&lt;li&gt;已完成的请求随时退出&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这能显著提升 GPU 利用率，同时尽量控制 TTFT。&lt;/p&gt;
&lt;h3 id="43-现实中的-trade-off"&gt;4.3 现实中的 trade-off
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;batch 越大，吞吐越高，但单步 decode 变慢（每步更重），可能拉高 TPOT&lt;/li&gt;
&lt;li&gt;请求长度差异越大，调度策略越重要（谁先跑、谁后跑）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个很实用的经验：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;把 TTFT 当成 SLO&lt;/strong&gt;（比如 P95 TTFT &amp;lt; 1.5s）&lt;/li&gt;
&lt;li&gt;在满足 TTFT 的前提下尽量追吞吐&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-请求层面的最划算优化减少无效-token"&gt;5. 请求层面的“最划算”优化：减少无效 token
&lt;/h2&gt;&lt;p&gt;很多团队上来就调 kernel、换引擎，但最便宜的优化其实是&lt;strong&gt;少算 token&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="51-prompt-预算管理"&gt;5.1 Prompt 预算管理
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;系统提示词别写成论文&lt;/li&gt;
&lt;li&gt;把固定指令改成短模板&lt;/li&gt;
&lt;li&gt;把“历史对话”做摘要而不是全量回灌&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="52-rag-的上下文压缩"&gt;5.2 RAG 的上下文压缩
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Top-K 不要盲堆（先加 rerank）&lt;/li&gt;
&lt;li&gt;召回后做“句级选择/段内抽取”&lt;/li&gt;
&lt;li&gt;对重复内容做去重&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每少 1k tokens 的 prefill，能直接省 latency 和成本。&lt;/p&gt;
&lt;h2 id="6-你应该怎么做一轮优化建议顺序"&gt;6. 你应该怎么做一轮优化（建议顺序）
&lt;/h2&gt;&lt;p&gt;我会按这个顺序做：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;建立基线&lt;/strong&gt;：记录 TTFT/TPOT、吞吐、显存&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;限制输入&lt;/strong&gt;：最大 context，RAG 截断/压缩&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调度策略&lt;/strong&gt;：连续 batching、合理并发上限&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;显存策略&lt;/strong&gt;：KV 管理、必要时量化&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更底层优化&lt;/strong&gt;：kernel/fused op、张量并行/流水并行（成本高）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;每一步都要做 A/B：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;质量是否回退（尤其长上下文与边界任务）&lt;/li&gt;
&lt;li&gt;P95 是否改善（别只看平均）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="结语"&gt;结语
&lt;/h2&gt;&lt;p&gt;LLM 推理优化的本质是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把“token”当成你的单位成本&lt;/li&gt;
&lt;li&gt;把 TTFT/TPOT 当成产品体验&lt;/li&gt;
&lt;li&gt;把 KV cache 当成核心资源&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你愿意，我可以再按你们的场景（RAG 为主？写作生成？多轮工具调用？）给一个更具体的配置建议清单：并发上限、上下文预算、检索 Top-K、rerank 以及监控指标应该怎么设。&lt;/p&gt;</description></item></channel></rss>