vLLM 高并发推理:从 KV Cache 瓶颈到性能监控调优
摘要
本文围绕高并发 AI 推理服务的三个层次展开:KV Cache 显存瓶颈与 PagedAttention 解决思路、Continuous Batching 调度机制、推测解码(Speculative Decoding)与 MEDUSA、EAGLE 加速方案,最后以 Qwen3-0.6B 在 RTX 4090D 上的部署实验验证 TTFT、TPOT、并发吞吐与 Prometheus 监控指标,并给出场景化调优建议。
vLLM 高并发推理:从 KV Cache 瓶颈到性能监控调优
写在前面
把大语言模型(Large Language Model,LLM)部署成线上服务时,真正决定服务能力的往往不是模型本身,而是推理引擎的显存管理、调度策略和解码方式。本文系统整理高并发 AI 服务的设计主线:先说明 KV Cache(Key-Value Cache,键值缓存)为什么是显存瓶颈,再解释 vLLM 如何用 PagedAttention 和 Continuous Batching 解决内存与调度问题,接着介绍推测解码(Speculative Decoding,投机采样)及其工程化变体 MEDUSA 与 EAGLE,最后在 RTX 4090D 上用 Qwen3-0.6B 完成部署、延迟测量、并发压测和 Prometheus(性能监控工具)指标采集,把原理落到可复现的工程流程。
模块 | 解决的核心问题 | 关键结论 |
|---|---|---|
KV Cache 与 PagedAttention | 高并发下显存被 KV Cache 占满、碎片化 | 块化存储与按需分配可节省 90% 以上显存 |
Continuous Batching | 静态批处理导致 GPU(Graphics Processing Unit,图形处理器)空闲 | 请求完成即补位,吞吐提升 2 倍以上 |
推测解码 | 小批量时 Decode 阶段算力浪费 | 草稿模型猜、目标模型验证,单请求延迟显著下降 |
性能监控与调优 | 瓶颈难以定位 | 用 TTFT、TPOT、KV Cache 利用率等指标做场景化调优 |
一、背景:高并发 AI 服务的内存瓶颈
1.1 KV Cache 是什么
Transformer 在自回归生成时,每一步都要让当前 token 与历史所有 token 做注意力计算。如果不做缓存,每生成一个新 token 都要重新计算前面所有位置的 Key(键)和 Value(值)张量,计算量随序列长度平方级增长。KV Cache 的思路是:把每一层已经算好的 K、V 张量保存下来,后续步骤只计算新位置的部分,避免重复计算。
以生成“我爱中国”为例,输入序列长度为 4:
步骤 | 输入 | 无 KV Cache | 有 KV Cache |
|---|---|---|---|
Step 1 |
| 计算 Q1、K1、V1,生成“爱” | 计算 Q1、K1、V1,缓存 K1、V1 |
Step 2 |
| 重新计算 K1、V1,再算 K2、V2 | 复用缓存的 K1、V1,只算 K2、V2 |
Step 3 |
| 重新计算 K1、K2、V1、V2 | 复用 K1..2、V1..2,只算 K3、V3 |
KV Cache 用显存换算力,但显存会随着上下文长度和并发请求数快速增长。
1.2 显存占用计算:KV Cache 才是显存杀手
以 LLaMA-2-7B 为例估算单请求的 KV Cache 占用:
每个 token 的 KV Cache = 2(K 和 V)x 32(层数)x 4096(隐藏维度)x 2(FP16,即 16 位浮点格式,每元素 2 字节)= 524,288 字节,约 0.5 MB。
上下文 4096 个 token 时,单个请求需要 4096 x 0.5 MB = 2 GB。并发 100 个请求就是 100 x 2 GB = 200 GB,远超单卡 A100(80 GB 显存)的容量。即使模型本身只占约 14 GB,KV Cache 在高并发场景下依然是真正的显存瓶颈。
1.3 KV Cache 的三大瓶颈
第一个瓶颈是内存碎片。内部碎片指为每个请求预分配最大长度(如 2048 个 token),实际只用 500,剩余空间被浪费;外部碎片指请求 A 占 0-500、请求 B 占 1000-1500,中间 500-999 虽然空闲,却因为不连续无法分配给需要连续内存的请求 C。
第二个瓶颈是动态长度导致的显存浪费。同一个系统里,有的请求只生成 100 个 token,有的要生成 2000 个 token,传统方案按最大长度预分配,平均利用率往往低于 30%。
第三个瓶颈是 Copy-on-Decoding 开销。使用 Beam Search(束搜索)时,需要把 KV Cache 完整复制到每个分支。每次复制量约为束宽 4 x 序列长度 1000 x 0.5 MB = 2 GB,而且每生成一个 token 都可能触发一次,严重拖慢生成速度。
二、PagedAttention:把显存当成虚拟内存管理
2.1 核心思想:块化存储与 Block Table
PagedAttention 借鉴操作系统虚拟内存的思想:虚拟内存把不连续的物理页映射给连续的虚拟地址,PagedAttention 则把不连续的显存块映射给逻辑上连续的序列。KV Cache 不再要求在物理显存中连续存放,而是分割成固定大小的 Block(块,通常 16 个 token 一块),通过 Block Table(块映射表)维护逻辑到物理的映射关系。
可以把这套机制类比成图书馆的目录卡片:一套丛书不必摆在连续的格子里,只要在目录上记录每一册的位置,读者依然能按顺序阅读。PagedAttention 就是 GPU 显存的目录卡片。

图 1 展示了 PagedAttention 的存储映射关系:上方是逻辑视图中的连续序列,中间是物理显存中的非连续存储,右侧是 Block Table。这张图对应一个明确结论:序列的逻辑连续性由映射表保证,物理上允许任意碎片化存放。
2.2 机制一:按需分配
传统方式在启动时按最大序列长度预分配显存,例如 2048 x 0.5 MB = 1024 MB,无论实际用多少都占满。PagedAttention 则生成 1 个 token 才分配 1 个 block,用满一个 block 才申请新 block。
生成 100 个 token 的序列时,需要 ceil(100 / 16) = 7 个 block,实际占用 7 x 16 x 0.5 MB = 56 MB;传统方式需要 1024 MB。按需分配节省约 94.5% 的显存。
2.3 机制二:写时复制
Beam Search 和 Parallel Sampling(并行采样)都面临同一个问题:多条路径或多个回复共享同一个 Prompt 前缀,KV Cache 完全相同,传统做法要完整复制多份。
PagedAttention 用写时复制(Copy-on-Write)解决:Prompt 阶段多个采样共享同一份 KV Cache,用引用计数记录共享数量;只有生成阶段真正产生分歧(输出不同 token)时才分配私有 Block。以 3 个并行采样为例,Prompt 阶段共享 5 个 block,生成阶段只新增 3 个私有 block,共 8 个 block;传统方式需要 3 x 6 = 18 个 block,节省约 55% 显存。
2.4 机制三:动态重排
当新请求到达时,PagedAttention 不需要寻找连续的大块显存,只需要收集分散的空闲 block 即可。这与停车场的逻辑一致:不需要一整排连续车位,有空位就能停。这一特性是 Continuous Batching 能够高效运转的前提。
三、vLLM 架构:Batch 与 Continuous Batching
3.1 Batch 的概念
Batch(批处理)指把多个用户请求打包在一起,送入 GPU 做一次前向传播。GPU 擅长并行计算,处理 1 个请求和同时处理 8 个请求的耗时差别不大,吞吐量却可以提升数倍,就像一辆公交车载 1 个人和载 30 个人跑一趟的油耗差不多。
假设同时有 3 个用户请求:A 需要生成 100 个 token,B 需要 200 个,C 需要 150 个。它们被放进同一个 batch,GPU 每一步同时为 3 个请求各生成 1 个 token。问题在于请求完成时间不同:短的先完成,长的还没结束,GPU 怎么处理空出来的位置?
3.2 静态 Batch 与 Continuous Batching
静态 Batch(同步等待)要求 batch 内所有请求都完成才释放资源,等待时间等于最长的那个请求,即 max(100, 200, 150) = 200 步。请求 A 完成后,对应位置要空闲 100 步,白白浪费算力。
Continuous Batching(连续批处理)在请求完成后立即从队列取新请求填入,GPU 始终满负荷运行,请求完成即刻腾出位置。vLLM 的调度粒度细到单次迭代,每生成一个 token 就检查一次,因此称为 Iteration-level Scheduling(迭代级调度)。

图 2 是两种调度的对比示意:静态 Batch 中先完成的请求仍然占位,直到整批结束;Continuous Batching 中请求完成立即释放,新请求马上补入。这一对比对应正文的核心结论,即动态补位消除了空闲等待。
以下数据来自对两种调度的性能对比:
指标 | 静态 Batch | Continuous Batching | 提升 |
|---|---|---|---|
GPU 利用率 | 40%-60% | 85%-95% | 1.5-2 倍 |
吞吐量(tokens/s) | 800 | 1800 | 2.25 倍 |
平均延迟(P50,第 50 百分位延迟) | 1200 ms | 800 ms | 1.5 倍 |
3.3 Iteration-level Scheduling 伪代码
每个 iteration(生成一个 token)调度一次,核心流程如下:
传统方案是 Request-level(请求级)调度,整个 batch 全部完成才处理下一批;vLLM 是 Iteration-level,每次前向传播后都检查并调度,相当于餐厅不等所有客人吃完才翻台,而是哪桌吃完就立刻安排新客人。
3.4 vLLM 系统架构与 PagedAttention 实现

图 3 是 vLLM 的系统架构总览,展示请求进入后由调度器管理 batch,显存由 Block Manager 统一分配,底层通过自定义 CUDA(Compute Unified Device Architecture,NVIDIA 并行计算平台)内核执行注意力计算。这张图说明 vLLM 不是一个简单的模型加载器,而是包含调度、显存管理与内核优化的完整推理引擎。
在实现层面,Block Table 是一个关键数据结构:
注意力计算时,KV Cache 是分散的,需要自定义 CUDA Kernel 按 Block Table 加载物理块再计算得分。性能优化的关键在合并内存访问:GPU 多个线程同时访问不同 block 的数据,把分散的小请求合并成少量大请求,充分利用显存带宽。
四、推测解码:让 Decode 阶段不再等待
4.1 为什么需要推测解码
自回归解码一次前向传播只能生成一个 token,当 batch 较小时,Decode 阶段属于 Memory-Bound(显存带宽受限),GPU 算力没有被吃满。推测解码的思路是:用一个更小的草稿模型(Draft Model)快速猜出接下来 K 个 token,再让目标模型(Target Model)一次前向验证整段草稿,把多次串行前向变成一次并行验证。

图 4 是推测解码的一次草稿与验证过程。绿色表示草稿模型提出且被目标模型接受的 token,红色表示被拒绝的 token,蓝色表示目标模型对被拒绝位置的订正。图中目标模型只推理了 9 次,就解码出 38 个 token,这就是推测解码的收益来源。
4.2 算法流程
推测解码来自论文《Fast Inference from Transformers via Speculative Decoding》(2023),完整流程分五步:
生成草稿:草稿模型自回归生成长度为 K 的候选 token 序列,并记录每个候选 token 的概率 p。
评分:目标模型对这 K 个候选 token 做一次前向传播,得到真实概率 q;这一步与评分单个 token 的耗时相当。
判断接受:对每个候选 token,以 min(1, q/p) 作为接受概率,生成均匀随机数判断接受还是拒绝。
处理结果:如果全部接受,直接从目标模型采样第 K+1 个 token;如果第 t 个被拒绝,则从修正概率分布 q(x) - p(x) >= 0 中采样一个新 token。
返回结果:把接受的草稿 token 与新采样 token 拼接作为最终输出。
关键性质是:被拒绝的 token 会从修正分布重新采样,数学上保证最终输出分布与原始模型一致,即推测解码不改变生成质量。只要草稿的平均命中 token 数大于 0,就有推理加速。
4.3 实验结果要点
论文用 T5-XXL(11B)作为目标模型,用 T5-large(800M)、T5-base(250M)、T5-small(77M)作为草稿模型,在英语到德语翻译和文本摘要任务上测量加速比。结论有三点:
比目标模型小几个数量级的草稿模型,其候选 token 被接受的概率 α(Alpha)通常在 0.5-0.9 之间。
对于所有模型,草稿分布调整得越尖锐,α 越高;即使简单的一元、二元近似模型也能产生非零的 α。
英语到德语翻译中,二元模型的 α 为 0.2,在草稿成本系数 c=0(草稿计算成本可忽略)时仍实现了 1.25 倍加速。
4.4 MEDUSA:去掉独立草稿模型
传统推测解码需要维护两个模型,工程上不够优雅。MEDUSA(论文《Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads》,2024)提供 One Model 方案:在原始模型解码器后面增加多个解码头(Medusa Heads),不做 Next-Token 预测,而是并行预测后 4 个 token 的候选。
Medusa 的训练成本很低:原始模型参数冻结,只微调解码头,单个 A100-80G GPU 一天内即可完成。但实验显示,每个 Head 只选 Top-1 时,预测 next-next token 的准确率只有约 60%,因此 MEDUSA 改为每个 Head 选 Top-k,构建树状候选结构,并用 Tree Attention(树状注意力)在单次前向中并行验证所有候选路径。Attention Mask 保证每个 token 只能看到自己和祖先节点,不能看到兄弟节点。
MEDUSA 还引入 Typical Acceptance(典型接受)策略:接受标准不是概率最高,而是信息量与分布熵接近的“典型”token,既不太可预测、也不太意外。温度参数控制接受严格度:温度高则接受更多候选、解码更快但质量可能下降。MEDUSA-1 实现约 2.2 倍加速,MEDUSA-2 联合微调主干与解码头后达到 2.83 倍,在数学、代码、抽取类任务上超过 3 倍。
4.5 EAGLE:在特征层做自回归
EAGLE(Extrapolation Algorithm for Greater Language-model Efficiency)的核心区别在于预测对象。传统推测解码在 token 层预测,但离散 token 的不确定性高,例如输入 “The capital of France is”,下一个词可能是 Paris、located 或 a;而在特征层(倒数第二层隐藏状态),Paris 对应的特征向量与 France、capital 在语义空间中距离很近,序列更连续、更规则、更容易预测。

图 5 对比了四类方法的草稿阶段:Speculative Sampling 与 Lookahead 基于 token 预测 token;MEDUSA 各解码头独立使用特征预测 token;EAGLE 使用特征序列和提前一个时间步的 token 序列预测下一个特征,再从特征采样 token。这张图对应一个结论:EAGLE 通过特征级自回归降低了草稿预测难度。
EAGLE 的草稿模型由三部分组成:嵌入层和 LM Head 直接复用目标模型参数(不需要额外训练),自回归头部由一个全连接层和一个解码器层组成,先降维融合特征与 token 嵌入,再预测下一个特征。草稿模型参数量很小,7B 模型仅 0.24B 可训练参数;LLaMA2-Chat 70B 在对话、代码生成、数学推理和指令遵循任务上实现 2.7-3.5 倍延迟加速。
三代 EAGLE 的演进如下:
版本 | 核心突破 | 解决的问题 | 加速比 |
|---|---|---|---|
EAGLE-1 | 特征级预测 + Shifted-Token | Token 预测不确定性高 | 约 3.0 倍 |
EAGLE-2 | 动态草稿树(上下文感知) | 静态树结构浪费计算 | 约 4.2 倍 |
EAGLE-3 | Training-time Test + 多层特征融合 | 特征约束限制 Scaling、训练与推理不一致 | 约 6.5 倍 |
EAGLE-2 的改进是动态草稿树:草稿模型的置信度与接受率强正相关,扩展阶段优先扩展全局接受概率高的节点,重排阶段重新排序所有候选并保证仍构成连通树,同时调整注意力掩码使不同分支不可见。相比静态树,计算资源集中到高概率分支,比 EAGLE-1 快 20%-40%。
EAGLE-3 解决的是 EAGLE-1/2 的隐藏瓶颈。传统训练输入是目标模型的真实特征,推理时输入却包含草稿模型自己生成的特征,误差随生成步数累积,第 5 步接受率从约 0.8 降到约 0.6,而且训练数据扩大 8 倍加速比几乎不增长。EAGLE-3 在训练时模拟推理的多步生成,让草稿模型适应自己的预测结果,各步接受率都保持在约 0.8。
大 batch 场景下差异尤其明显:SGLang 测试中 batch=64 时,EAGLE-1/2 吞吐量降到 0.99 倍(几乎无加速),EAGLE-3 仍保持 1.38 倍。原因是大 batch 下 GPU 已经接近 Compute-Bound(算力受限),草稿计算边际收益小,草稿质量就成了决定因素。这给工程选型一个明确结论:高并发生产环境中,EAGLE-3 是目前能同时兼顾大 batch 高吞吐与推测解码加速的方案。
4.6 推测解码与 vLLM 的集成
推测解码与 Continuous Batching 结合时有三个冲突点,对应的解决方案:
冲突点 | 解决方案 |
|---|---|
草稿阶段需要 batch=1,Continuous Batching 需要动态 batch | 草稿阶段作为独立 micro-batch,验证阶段合并入主 batch |
MEDUSA 等 Tree Attention 需要特殊 Mask | vLLM 支持自定义 Attention Backend |
草稿模型与 KV Cache 的显存碎片 | PagedAttention 统一管理草稿和目标模型的 KV Cache |
以 EAGLE + vLLM 为例,单次 Iteration 的流程是:先选择 batch 中序列最长或历史接受率高的请求;再用 EAGLE 草稿模型(0.24B 参数)树状采样 3-5 步生成候选树;目标模型通过 Tree Attention 并行验证所有候选;最后更新 Block Table,保留被接受 token 的 block,释放被拒绝的 block。
五、vLLM 性能监控与调优
5.1 关键性能指标
监控 vLLM 服务首先需要一组明确指标:
指标 | 含义 | 观测方式 |
|---|---|---|
TTFT(Time To First Token,首 Token 延迟) | 从请求发出到收到第一个输出 token 的时间 | 流式输出时间戳 |
TPOT(Time Per Output Token,每输出 Token 耗时) | 相邻输出 token 的间隔 | 流式输出时间戳 |
吞吐量 | 每秒生成的 token 数(tokens/s) | 压测统计 |
接受率 α | 草稿 token 被目标模型接受的比例 |
|
接受率可以理解为猜题命中率:草稿模型猜了 5 个 token,目标模型验证后接受 3 个,则 α = 0.6。接受率越高推测解码加速越明显;接受率太低时,草稿计算就是纯开销。
延迟分位数 P50、P95、P99 分别表示第 50、95、99 百分位的延迟,用于衡量不同负载水平下的典型延迟和尾延迟。P50 反映多数请求的体验,P99 反映最差情况下的体验,是并发压测中观察饱和拐点的关键指标。
5.2 核心优化参数
vLLM 的启动参数按目标可分为四类,实际部署时按“高吞吐、低延迟、省显存”三个目标组合:
类别 | 参数 | 说明 |
|---|---|---|
并行与分布式 |
| 张量并行(Tensor Parallelism,TP),按 GPU 数切分 |
并行与分布式 |
| 流水线并行(Pipeline Parallelism,PP),大模型跨节点使用 |
并行与分布式 |
| 数据并行(Data Parallelism,DP),高并发场景 |
内存与 KV Cache |
| 最大序列长度,按实际需求设置避免浪费显存 |
内存与 KV Cache |
| 最大批处理 token 数,越大吞吐越高 |
内存与 KV Cache |
| 最大并发序列数,按显存与序列长度调整 |
内存与 KV Cache |
| KV Cache 数据类型,fp8 可省显存且损失小于 1% |
内存与 KV Cache |
| 分块预填充,强烈建议开启 |
内存与 KV Cache |
| 前缀缓存,多轮对话场景必开 |
内存与 KV Cache |
| GPU 显存利用率上限,推荐 0.90-0.95 |
量化与加载 |
| 量化方式:awq、gptq、fp8、int8 等 |
量化与加载 |
| 计算精度:float16、bfloat16、float32 |
推测解码 |
| 草稿模型路径 |
推测解码 |
| 推测 token 数,建议 3-5 |
推测解码 |
| 草稿模型 TP,通常为 1 |
调度与抢占 |
|
|
调度与抢占 |
|
|
5.3 监控工具栈
vLLM 内置 Prometheus 格式的 Metrics,启动时加 --enable-metrics 参数即可暴露:
深度分析可以用 NVIDIA Nsight Systems 做 Kernel 级分析,例如 nsys profile -o vllm_profile python -m vllm.entrypoints.openai.api_server,用于判断 Attention 内核是否成为瓶颈;生产环境则用 Grafana Dashboard 汇总关键指标做秒级监控。
5.4 场景化调优策略
场景一:TTFT 过高(大于 2 秒)。先诊断:如果 prompt 长度超过 4096 且并发请求超过 10,瓶颈是 Prefill 计算受限;如果 KV Cache 利用率超过 0.9,瓶颈是显存受限触发换出。对应解法:Chunked Prefill 把长 prompt 拆成 512 token 的小块与 decode 交错执行,避免长 prompt 独占 GPU;Prefix Caching 复用系统提示词的 KV Cache;必要时做 PD 分离,即把 Prefill(预填充阶段)和 Decode(解码阶段)分开部署。Chunked Prefill 有效的本质是分时复用,就像长途车每跑一段就让出车道给短途车。
场景二:TPOT 抖动大。先诊断 batch size 波动(1-32)和推测解码接受率骤降。对应解法:用 --max-num-seqs 64 控制 batch 波动上限;高温度(大于 0.8)时把草稿长度从 4 降到 2 或使用 Typical Acceptance;PD 分离后 Decode 独立运行,TPOT 更稳定。
场景三:GPU 利用率低于 50%。先诊断是 Memory-Bound(序列过长、显存占满但计算未满)还是通信开销(张量并行时 NVLink,即 NVIDIA 高速互联,成为瓶颈)。对应解法:增大 --max-num-seqs 直到 GPU 计算利用率达到 85% 以上;用 --quantization fp8 --kv-cache-dtype fp8 省显存提吞吐;batch 小于 8 时启用推测解码获得 2-3 倍加速。注意 batch 增大后推测解码效果会减弱,因为 GPU 已经从 Memory-Bound 转为 Compute-Bound,草稿模型的额外计算反而成为负担。
六、实战:Qwen3-0.6B 部署与性能测量
6.1 实验环境与启动配置
实验环境为 RTX 4090D(24 GB 显存)、Qwen3-0.6B(FP16)、vLLM 0.18.0。基础启动命令如下:
启动脚本内置了四个场景配置,对应不同优化目标:
场景 | 关键参数 | 优化目标 |
|---|---|---|
basic | 默认参数 | 快速验证环境可用 |
high_throughput |
| 最大化 tokens/s |
low_latency |
| 最小化 TTFT/TPOT |
save_memory |
| 避免显存不足 |
服务启动后先用基础对话验证:单轮对话直接调用 OpenAI 兼容接口,多轮对话把历史消息追加到 messages 中,验证 Continuous Batching 下多轮交互正常,并检查 usage 中的输入输出 token 数。
6.2 CASE 1:流式输出与延迟测量
通过 stream=True 记录每个输出 chunk 的到达时间,可以精确计算 TTFT 和 TPOT:
分别用短、中、长三种 prompt 测试,结果如下:
测试场景 | TTFT (ms) | TPOT 平均 (ms) | TPOT P50 (ms) | TPOT P95 (ms) | 吞吐 (tok/s) |
|---|---|---|---|---|---|
短 Prompt(“你好”) | 355.5 | 13.6 | 14.0 | 14.8 | 58.8 |
中 Prompt(自注意力机制) | 40.0 | 8.8 | 8.6 | 10.1 | 111.8 |
长 Prompt(PagedAttention 背景 + 问题) | 63.2 | 9.3 | 9.1 | 10.5 | 106.3 |
一个反直觉的现象是短 Prompt 的 TTFT 反而最高(355.5 ms)。这是冷启动效应:第一个请求时 GPU 的 CUDA Kernel 尚未预热,包含即时编译(JIT,Just-In-Time)和内存分配,导致首次 TTFT 显著偏高;后续请求完成预热后回落到 40-63 ms。生产环境通常先发送预热请求,避免冷启动影响首批用户。
6.3 CASE 2:并发压测
压测脚本用线程池以指定并发度发送 20 个请求,统计 QPS(Queries Per Second,每秒查询数)、吞吐量与延迟分位数:
分别以 1、2、4、8、16 并发度测试,结果如下:
并发度 | QPS (req/s) | 吞吐量 (tok/s) | P50 延迟 (ms) | P99 延迟 (ms) |
|---|---|---|---|---|
1 | 1.02 | 101.0 | 899.8 | 1453.9 |
2 | 2.02 | 201.6 | 985.1 | 1048.2 |
4 | 3.85 | 385.4 | 1018.2 | 1128.3 |
8 | 6.35 | 635.0 | 1037.3 | 1101.5 |
16 | 9.87 | 987.2 | 1520.6 | 2085.3 |
两组关键结论:
并发从 1 升到 8,吞吐量从 101 增长到 635 tok/s(约 6.3 倍),P50 延迟只从约 900 ms 增至 1037 ms(约 15%),这正是 Continuous Batching 的效果:GPU 并行处理多个请求,吞吐随并发近似线性增长。
并发到 16 时出现拐点:P99 延迟跳升到 2085 ms,说明 GPU 算力接近饱和,服务从 Memory-Bound 转向 Compute-Bound。压测验证了理论预期:处理 1 个请求和 8 个请求的单请求耗时差别不大,但总吞吐量随并发近似线性增长。
6.4 CASE 3:Prometheus 指标采集
从 /metrics 端点采集并解析关键指标,用正则提取 Counter/Gauge 类型数值,并用 bucket 数据估算 TTFT、TPOT 分位数:
负载前后对比:
指标 | 负载前 | 负载后(20 个并发请求) | 增量 |
|---|---|---|---|
输入 token 累计( | 6,514 | 6,774 | +260 |
生成 token 累计( | 21,634 | 24,634 | +3,000 |
持续监控模式每 2 秒采集一次,负载期间输出如下:
指标解读:
生成速度约为每 2 秒新增 900 tokens,即约 450 tok/s 的实际吞吐(8 并发 x 约 56 tok/s/请求),与并发压测的 635 tok/s 处于同一量级。
KV Cache 利用率为 0% 是因为 Qwen3-0.6B 模型很小(约 1.12 GB),RTX 4090D 有 24 GB 显存,KV Cache 占比极低;换成 7B/13B 模型或更长上下文,该指标会显著上升,此时
vllm:gpu_kv_cache_usage_percent才是核心监控对象。运行中请求数为 0 是因为 vLLM 0.18.0 的部分 Gauge 指标在两次采样之间请求已完成;生产环境应搭配 Grafana 做秒级连续采集,避免采样窗口漏掉瞬时状态。
七、总结
高并发 AI 服务的优化路径可以归纳为三层:
第一层是显存管理。KV Cache 是并发扩展的物理约束,PagedAttention 用块化存储、按需分配、写时复制解决碎片与浪费,这是所有上层调度的基础。
第二层是调度策略。Continuous Batching 把调度粒度从请求级细化到迭代级,请求完成立即补位,让 GPU 保持满载,实测并发从 1 升到 8 时吞吐增长约 6.3 倍而 P50 延迟仅增 15%。
第三层是解码加速。小 batch 时推测解码把 Decode 阶段从 Memory-Bound 变成 Compute-Bound,MEDUSA 与 EAGLE 分别从多头预测和特征级预测两条路线去掉或弱化独立草稿模型;EAGLE-3 通过训练时模拟推理误差,在大 batch 高并发下仍保持 1.38 倍吞吐提升。
工程上的选择条件可以这样判断:batch 小、GPU 利用率低时优先启用推测解码;batch 已经很大时靠 Continuous Batching 和增大 --max-num-seqs 吃满算力,推测解码可能反而拖后腿;长 prompt 场景优先 Chunked Prefill 与 Prefix Caching;显存紧张时用 fp8 量化与 --kv-cache-dtype fp8。无论哪种场景,都应该先建立 TTFT、TPOT、吞吐量、KV Cache 利用率等指标的监控基线,再按指标做参数调整,避免凭感觉调参。
