主要概念与痛点一览
在 LLM 推理中,最常见的三大痛点是:GPU 空转显存浪费和Prefill/Decode 混批效率低。这三大罪行导致吞吐量低、延迟抖动、资源利用率差。下面按技术细分,逐条剖析方法与工程落地。不过,
1️⃣ Continuous Batching:让 GPU 永不空转
痛点:每个 batch 里最短请求先跑完后 GPU 就闲置。
-
Orca 的迭代级调度: 把调度粒度从请求降到迭代。每一步都检查 EOS/新请求,实时填充。
-
vLLM 进一步演进为 PagedAttention kernel: 在每一步可 batch 组合,保持 GPU 利用率高。
-
实现要点: Python 调度开销极高 → vLLM v1 将调度移到 C++;块管理需较快完成,否则会成为瓶颈。
2️⃣ PagedAttention:把 KV Cache 做成“虚拟内存”
痛点:显存碎片化导致实际可用 KV 远低于理论值。
-
PagedAttention 操作程序类比: KV 切块→物理映射表→按需读取;不再要求连续显存,
-
COW 与引用计数支持多路复用: 共享前缀块,省去重复 prefill 与 KV 空间。
-
C++/CUDA 调整成本很小,只是一次间接跳转;显存利用率提高带来的吞吐增益远大。
-
block_size 选取建议:- 默认 16 token/block;- 极端短 prompt 可尝试更小;- 长上下文则保持默认或更大以减少碎片。
-
⚠️注意:PagedAttention 必须配合
enable-prefix-caching/enable-chunked-prefill;话说回来,否则无法发挥全部优势。
3️⃣ Chunked Prefill:消除 TTFT 抖动与 P99 TPOT 爆炸
痛点:长 prefill 阻塞 decode,导致尾延迟飙高。
-
SARATHI 的 Chunked Prefill 思想: 把 long prefill 切成若干 chunk,与 decode 同 batch 并行执行。
-
✅优点:- 每步 token 数固定 → 延迟波动小;- decode 不被长 prefill 阻塞 → TPOT 稳定;- 单条 request 的 TTFT 可控。
-
⚠️缺点:- 单条 request 的总 prefill 时间略增长。说起来,对 TTFT 敏感场景请先评估是否接受此 trade‑off。
-
⚠️参数 tuning:-
max_num_batched_tokens : 越大吞吐越好但延迟波动加剧;- M=2048~8192 通常能平衡吞吐 & 延迟。建议通过 SLA 定位最佳值。
4️⃣ Prefix Caching:省下重复 Prefill 与 KV 显存成本
痛点:程序 prompt / few-shot / RAG 前缀频繁重复,却每次都重新计算并占用显存。
-
: 按 block 级 hash 对前缀进行唯一标识,命中直接复用物理 block。✅效果:- 前缀命中率 ≥80% 时 TTFT 降低 ~10x;- 显存占用降低 ~百分之三十。⚠️注意:- 必须保证 tokenizer 一致性,否则哈希会失效导致 miss。其实,⚠️隐私安全:- 前缀缓存共享全局时需做 tenant 隔离。否则敏感数据泄露风险提高。
-
SGLang 的 Radix Attention : 用基数树结构管理 token 序列。实现 token‑级命中,比 hash 更细粒度
✅适合场景:- Agent、ReAct、多轮对话等前缀分叉频繁的工作负载;- 命中率可达95%以上。
-
⚠️部署注意事项:- prefix_cache_evict_rate 高 → 表示显存池紧张,需要增加 GPU 或缩短前缀长度;说起来,- 多租户环境务必在网关层做 tenant key 控制缓存访问。
-
PREFIX 缓存往往需要多级结构,尤其在长上下文 或多机集群下极为关键。
-
再看L1,GPU HBM – 高速、容量有限
-
说到L2,CPU DRAM – 中速 、容量中
-
L3的观点是,NVMe / 分布式 – 低速 、容量大
5️⃣ Priority Scheduling & Swap/Recompute 抢占策略
痛点:当显存不足时新长请求被阻塞或老请求被强制抢占。
造成 OOM 或性能下降.
Sweep — 将抢占 seq 的 KV 写入 CPU 内存,通过 PCIe 拷出
- 优势: 保留已生成的结果,不需要重新 compute
- 劣势: PCIe 带宽受限,多卡 TP 下可能反而更慢
Deref — 直接释放 seq 所有 block,再从头 re‑prefill
- 优势: 无 IO 开销
- 劣势: 重算 cost = 已生成的 compute + 新 prefill
至于⚡经验法则,
-
seq 短且抢占偶发 → 使用 Swap;
\
seq 长且抢占持续 → 使用 Recompute;.
您可以通过 vLLM 参数如 --preempt_mode 来选择策略,并结合监控指标 vllm:num_requests_swapped 与 vllm:num_requests_recomputed 做动态切换。
至于实战教程,如何快速上线 vLLM 并开启主要功能?
1️⃣ 快速部署 OpenAI‑兼容服务器
pip install vllm
vllm serve Qwen/Qwen2.-7B-Instruct \
--host localhost --port 8000 \
--tensor-parallel-size=1 \
--gpu-memory-utilization=0.7 \
--max-model-len=4096 \
--max-num-batched-tokens=4096 \
--max-num-seqs=128 \
--enable-prefix-caching \
--enable-chunked-prefill
访问 即可直接使用 OpenAI SDK。
2️⃣ 参数解读与默认值建议
| 参数名
含义
建议 |
| `--gpu-memory-utilization`
KV pool 占比
**建议** 0.6–0.8
过高易抢占/OOM 过低浪费资源
|
| `--max-num-seqs`
最大并发 sequence 数目
**建议** ≤ `gpu_memory_utilization * total_gpus * capacity_factor`
|
| `--max-num-batched-tokens`
单 step 最大 token 数量
**建议** 2048–8192
|
`--block-size`
default 16 tokens/block
*如果你有极短 prompt。考虑改为8*
*如果你追求极限吞吐,可以尝试32*
**提示** 改变 block_size 会影响内部指针大小与 cache 对齐,请先压测再改
`--kv-cache-dtype`
‑ KV precision,default auto.
高阶使用者可开启 FP8 减半显存。
3️⃣ Promeus 指标监控要关注哪些?**
| 指标 |
含义 |
理想区间 |
vllm:num_requests_running |
当前正在推理的 request 数量 |
接近 max_num_seqs。则 batch 满 |
vllm:num_requests_waiting |
排队等待的 request 数量 |
≤10 时正常 |
vllm:num_requests_swapped/recomputed |
被 swap / recompute 的次数 |
小于总请求数的 % |
vllm:gpu_cache_usage_perc |
KV 池利用率 |
70–90% 健康 |
vllm:prefix_cache_hit_rate |
前缀命中率 |
≥80% 为佳 |
vllm:time_to_first_token_seconds,time_per_output_token_seconds,e2e_request_latency_seconds |
延迟指标 |
按业务 SLA |
4️⃣ 调参决策树示例
┌─ 服务刚上线?│ ├─ 默认 GMU=0.7,maxseq=128。maxbatchtoken=4096
│ └─ 开启 prefix + chunked 若 TTFT 高?话说回来,│ ├─ 查看 maxnumwaiting 是否>30 => 加卡或降 maxlen
│ ├─ 长 prompt?增 maxbatchtoken 并观察 chunked 是否启用
│ └─ 若 prefix 固定且 TPOT 高?│ ├─ 检查 prefill/decode 混批比例,缩小 prefill chunk size
│ └─ 看是否有超长 seq 在 decode 中 -> 考虑降 max_len 或开启 FP8 KV cache
┌─ OOM 或 swap 高频?│ ├─ 降 GMU 至0.6 或更低;│ ├─ 降 maxnumseqs;其实,│ ├─ 开启 FP8 kvcachedtype;│ └─ 考虑减少 batch size 或使用 multi‑LoRA 管理内存。
┌─ 吞吐瓶颈?│ ├─ 增加 maxnumseqs 或者减小 block_size;│ └─ 升至 vLLM v1 并开启 CUDA Graph 捕获。
5️⃣ 多机多卡部署简易脚本
bash
vllm serve meta-llama/Llama--70B-Instruct \
--tensor-parallel-size=12 \
--pipeline-parallel-size=1 \ # 单机 PP 为1即可\
--gpu-memory-utilization=0.75
ray start --head # Node0 head node
ray start --address=:6379 # Node1 worker node
ray start ...
vllm serve meta-llama/Llama--405B-Instruct \
--tensor-parallel-size=24 \ # 总卡数÷PP=
--pipeline-parallel-size=\
...
6️⃣ 灰度与回滚流程
-
离线 Benchmark 用业务真实 prompt 压测 QPS/TTFT/TPOT。
-
金丝雀流量 在生产环境跑少量流量观察 SLA、OOM 次数。
-
逐步放量 每步流量增加比例至满负载并监控关键指标。
-
备份旧镜像 保持旧版本容器及配置,以分钟级别切回。
常见问答速查
| 问题标题 | 答案 |
| 开 prefix caching 是否影响结果确定性? | 不会。怎么说呢,命中即表示该段已计算完毕,与
计算得到相同结果一致。仅可能出现微小浮点误差,但对生成质量无实质影响。 |
| chunked prefill 会使单条请求慢吗?说起来, | 略微慢 ~5–10%。但整体吞吐上升且尾延迟下降,多数业务接受此 trade‑off。 |
| 自己实现 PagedAttention kernel 难吗? | 实现难,但不推荐。有成熟实现如 FlashInfer、xFormers 等已覆盖多种变体,可直接使用以避免边界 bug。 |
| 分离部署 vs chunked prefill 哪个更适合?老实说, | `分离部署适合百卡/千卡大型集群、对 TTFT/TPO 严格 SLA 场景。需要额外处理 KV 路由和跨机传输,相比之下仅需修改配置就可以完成 chunked prefill,对中小规模更友好且实现成本低。”——来自实践表格内容.t d /> |
|
|
<\/table>
🚨 FAQ 快速查看
-
"如果我只服务付费 API,我应该怎么做?" — 在网关层做优先级 + rate‑limit,并在引擎层启用 priority scheduling + swap/recompute 策略。以保证高 SLA 对齐.
📚 推荐阅读路线图
-
attention kernel 层调整思路..
• 阅读关于128K+上下文
章节.
• 如果想进一步节省显存请阅读 FP8 / INT4 部分.
• 对比两者在 Agent & Tree Search 场景下表现.
• 跟随官方教程进行网关 + 多副本架构搭建.
🔧 工程实操清单
| 步骤 |
主要动作 |
| ✅ 引擎选择 & 配置启动 |
打开 continuous batching + paged attention + prefix caching + chunked prefill |
| ⚙️ 参数 fine‑tune |
调整 gpumemoryutilization、maxnumbatchedtokens、blocksize 等 |
| 📊 指标监控 |
跟踪 gpucacheusageperc、prefixcachehitrate、TTFT/TPO 等 |
| 🚧 灰度迁移 |
分阶段增加流量并验证 SLA 与错误率 |
| 🔁 回滚准备 |
保持旧镜像及配置随时切换 |
。