LLM Inference Optimization Map
LLM Inference Optimization Map
指标
- TTFT:首 token 延迟,常受排队与 prefill 影响。
- TPOT:后续每 token 延迟,常受 decode 与 batch 状态影响。
- Throughput:单位时间完成的 tokens 或 requests。
- P95/P99:尾延迟。
- GPU 利用率、KV cache hit rate、error rate 与成本。
优化层次
| 层 | 方法 |
|---|---|
| 模型结构 | MQA/GQA、MoE、MTP |
| 精度/压缩 | weight、activation、KV quantization |
| Kernel | FlashAttention、FlashInfer、Triton、CUDA Graph |
| 内存管理 | KV Cache、PagedAttention、prefix cache、offload |
| 调度 | Continuous Batching、chunked prefill、priority/admission control |
| 解码算法 | Speculative Decoding、EAGLE、Medusa |
| 分布式 | TP/PP/EP、Prefill-Decode Disaggregation、KV transfer |
| Serving | routing、autoscaling、multi-model、backpressure |
优化不能只看 tokens/s。提高吞吐可能恶化单请求延迟,跨节点 TP 可能因通信反而变慢,量化也可能受 kernel 与反量化开销影响。
量化格式的分层判断
精度/压缩这一层不能只看“几 bit”。至少要区分:
| 层 | 代表 | 回答的问题 |
|---|---|---|
| 数值格式 | BF16、FP8、NVFP4、INT8/INT4 | 一个数怎么表示 |
| 权重编码 recipe | K-quant、I-quant、AWQ/GPTQ | 一组权重怎么分 block、scale 和码本 |
| 动态分配策略 | Unsloth Dynamic(UD) | 不同 tensor/layer 分别用哪种量化 |
| 文件容器 | GGUF、Safetensors | 量化结果和元数据如何打包 |
因此 UD-Q4_K_XL 不是新的单一数据类型:它仍以 Q4_K 为主体,只是按 tensor 敏感度混合更高精度。评价时还要看实际 bpw、imatrix/calibration 数据、kernel 支持和任务回归,而不是只看名称里的数字。
按症状定位,而不是按热度选技术
| 症状 | 先查什么 | 可能方向 |
|---|---|---|
| TTFT 高、TPOT 正常 | 排队、tokenize、长 prompt、prefill | admission、chunked prefill、prefill 资源 |
| TPOT 高 | 权重/KV 搬运、decode batch、kernel | batching、GQA、量化、speculative decoding |
| 吞吐高但 P99 高 | 长短请求混合、公平性、抢占 | continuous batching、priority、隔离池 |
| 显存先满、GPU 不满 | KV fragmentation、workspace、长度分布 | paged KV、量化、限流、cache policy |
| 多卡扩展不线性 | All-Reduce/All-to-All、拓扑 | TP/PP/DP 重配、网络优化 |
优化顺序通常是:先建立真实流量基线和 SLO,再解决硬容量约束,再优化调度/内存,最后尝试改变计算路径的模型或 speculative 方案。没有基线时,优化后的提升无法区分来自缓存命中、batch 变化还是请求分布漂移。
横向关系
- KV Cache 是容量与带宽的共同约束;Continuous Batching 是调度层杠杆。
- PagedAttention 减少分配浪费,但不能替代容量规划。
- Speculative Decoding 用额外 draft/verify 计算换串行步数,命中率低时可能反而变慢。
- Prefill-Decode Disaggregation 拆开冲突的资源画像,却新增 KV transfer 与路由成本。
每次只改变一个主要层级,并保留相同模型、请求轨迹、硬件和版本;否则无法知道是哪条因果链被优化。
把优化拆成可证伪的实验
一轮优化至少需要一个 baseline 和一个只改变单一机制的 candidate:
| 实验 | 只改变什么 | 主要读数 | 失败时说明 |
|---|---|---|---|
| baseline → batching | 静态/连续调度 | TPOT、有效 batch、P99 | scheduler/容量仍是瓶颈或公平性恶化 |
| baseline → quant | 权重或 KV 精度 | 显存、kernel、质量 | fallback/反量化吃掉收益 |
| baseline → speculative | draft/k | 接受长度、draft 时间、TPOT | 接受率低或 batch 不适合 |
| baseline → TP/DP | 并行映射 | collective、扩展比、尾延迟 | 拓扑/通信成为主瓶颈 |
压测输入要按至少两个轴分桶:prompt 长度与生成长度;再加入前缀重复率、突发到达和取消率。这样才能区分 prefill 变快、decode 变快、KV 命中和单纯减少了请求量。任何“提升 X%”都应同时写出工作负载、并发、硬件、版本、warmup、指标定义和重复次数。
先修供需,再换算法
如果显存快满导致 admission 拒绝,先处理 KV block 浪费、上下文上限和限流;如果请求大多在队列里,先查路由、冷启动和调度公平;只有在设备已经稳定供给请求后,才有意义比较 kernel、量化或 speculative。否则把一个队列瓶颈误判成算力瓶颈,会得到“离线 benchmark 变快、线上没有变化”的假优化。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Lux's Blog!