大模型推理服务指标设计
如果是大模型推理服务的运维系统,指标设计不能只停留在 CPU、内存、GPU 利用率这一层。推理服务真正要回答的是三个问题:
服务是否可用?请求是否足够快?昂贵的 GPU 是否被高效利用?
因此一套比较完整的推理服务监控体系,通常需要同时覆盖 请求层、模型执行层、调度层、GPU 硬件层、节点与网络层、容量与成本层。
1. 先建立推理服务的数据链路
一个典型的大模型推理请求大致会经过:
Client
│
▼
API Gateway / Load Balancer
│
▼
Inference Server
│
├── Request Queue
│
├── Scheduler / Batcher
│
├── Tokenizer
│
├── Prefill
│
├── Decode
│
└── KV Cache
│
▼
GPU
│
├── SM / Tensor Core
├── HBM
├── PCIe
└── NVLink
所以监控也应该沿着这条链路设计,而不是孤立地采集几十个指标。
2. 第一层:服务可用性指标
这是最基础的一层,主要回答:
请求能不能正常完成?
重点指标包括:
- 请求总量
- 成功请求数
- 错误请求数
- HTTP 4xx / 5xx
- timeout 数量
- canceled request
- 请求成功率
- 服务实例健康状态
例如:
rate(inference_requests_total[5m])
请求错误率:
rate(inference_requests_failed_total[5m])
/
rate(inference_requests_total[5m])
如果定义:
那么推理平台最基本的 SLI 就是:
Availability
例如:
99.9% requests successful
不过对于推理服务来说,请求成功并不等于服务健康。
如果一个请求:
最终返回成功
但耗时 40 秒
用户体验仍然非常差。
所以延迟指标比普通 Web 服务更加重要。
3. 第二层:端到端请求延迟
最基本的是:
Request Latency
即:
通常不能只监控平均值。
应该重点看:
P50
P90
P95
P99
P99.9
例如:
P50 = 2s
P95 = 5s
P99 = 18s
说明绝大部分请求正常,但长尾已经非常严重。
在推理服务中,长尾延迟尤其重要,因为一个慢请求可能意味着:
- 排队严重
- 某张 GPU 成为 straggler
- KV Cache 不足
- batch 太大
- 某些请求 prompt 特别长
- 多卡通信异常
4. LLM 推理里最重要的指标之一:TTFT
普通 HTTP 服务一般只关注:
总延迟
但大模型流式生成不一样。
用户真正感知的第一个时间是:
第一个 token 多久出来。
这就是:
TTFT — Time To First Token
定义可以写成:
例如:
请求到达 0ms
开始执行 100ms
首token返回 800ms
那么:
TTFT = 800ms
TTFT 主要受:
- queue time
- prompt length
- prefill 阶段
- batch 调度
- GPU 负载
影响。
对于聊天机器人来说,TTFT 往往比总响应时间更直接影响用户体验。
5. 第二个核心指标:TPOT / ITL
第一个 token 出来之后,还要持续生成。
因此还需要关注:
TPOT — Time Per Output Token
以及:
ITL — Inter-Token Latency
可以近似理解成:
后续每个 token 之间间隔多久。
例如:
token1 1.0s
token2 1.05s
token3 1.10s
token4 1.15s
那么:
≈ 50ms/token
对应输出速度:
如果:
那么:
这就是推理服务非常重要的性能指标。
6. 为什么 TTFT 和 TPOT 必须分开看
因为 LLM 推理有两个不同阶段:
Prompt
│
▼
Prefill
│
▼
Decode
│
▼
Generated Tokens
Prefill 阶段通常:
- 一次处理大量 prompt token
- 计算密集
- Tensor Core 利用率较高
Decode 阶段:
- 每次生成一个 token
- 更依赖 KV Cache
- 更容易 memory-bound
因此:
TTFT 高
TPOT 正常
通常更倾向:
Prefill / 排队阶段有问题。
而:
TTFT 正常
TPOT 高
则更倾向:
Decode 阶段性能不足。
这比单纯看:
P99 latency
信息量大得多。
7. 第三层:Token 吞吐指标
推理服务真正处理的不是“HTTP 请求”,而是 token。
因此至少应该采集:
input_tokens_total
output_tokens_total
以及对应速率。
输入吞吐:
input tokens / second
输出吞吐:
output tokens / second
总吞吐:
tokens / second
例如:
GPU A:
1000 req/min
50k tokens/s
GPU B:
1000 req/min
20k tokens/s
请求数一样,但 A 实际完成了更多推理工作。
所以对于 LLM:
tokens/s 通常比 requests/s 更接近真实吞吐能力。
8. Prompt 长度和输出长度
必须监控:
input token length
output token length
sequence length
因为这三个指标直接决定负载。
例如:
请求 A:
Prompt = 100 tokens
Output = 100 tokens
请求 B:
Prompt = 20000 tokens
Output = 2000 tokens
不能认为两个请求消耗相同资源。
所以最好记录:
- average input tokens
- P95 input tokens
- average output tokens
- P95 output tokens
甚至按照模型和用户请求类别分组。
否则可能看到:
requests/s 下降 30%
却误判为性能下降。
实际上只是:
最近请求长度变长了。
9. 第四层:请求队列指标
推理服务通常不会请求一来就立即执行,而是:
Request
↓
Queue
↓
Scheduler
↓
Batch
↓
GPU
所以必须监控:
queue length
queue wait time
pending requests
running requests
其中非常重要的是:
Queue Time
如果:
TTFT = 5s
Queue Time = 4.5s
说明 GPU 算力本身未必有问题。
真正的问题是:
请求等待调度。
所以:
TTFT
=
Queue Time
+
Prefill Time
这是一个非常有价值的分解关系。
10. 第五层:Batching 指标
现代 LLM 推理引擎普遍使用:
Continuous Batching
核心思想是:
把多个不同生命周期的请求动态拼到同一批次里运行。
所以监控系统需要记录:
batch size
active sequences
scheduled tokens
batch utilization
例如:
GPU Util = 40%
batch size = 1~2
queue length = 100
这非常不正常。
意味着:
明明大量请求在等待,但是 batcher 没有有效把请求送进 GPU。
可能是调度参数问题。
相反:
GPU Util = 95%
batch size = 64
queue length = 0
说明 GPU 被充分利用,而且目前没有明显排队。
11. 第六层:KV Cache
对于大模型推理来说,这是和普通 GPU workload 区别最大的部分之一。
Transformer decode 阶段会保存前面 token 的:
Key
Value
形成:
KV Cache。
可以粗略理解:
Prompt + 已生成Token
│
▼
KV Cache
│
▼
下一次生成无需重新计算所有历史状态
所以 KV Cache 能显著加速生成。
但它需要大量显存。
因此必须监控:
KV Cache used
KV Cache free
KV Cache utilization
KV Cache eviction
KV Cache allocation failure
如果:
KV Cache Usage = 98%
随后出现:
queue length ↑
TTFT ↑
就很可能说明:
KV Cache 已经成为系统容量瓶颈。
12. KV Cache 为什么比普通显存指标更重要
假设:
GPU memory used = 70%
看起来还有很多显存。
但真正给 KV Cache 预留的区域可能已经:
KV Cache utilization = 99%
那么新请求可能仍然无法调度。
因此:
GPU Memory Usage
只能说明:
GPU 总显存用了多少。
而:
KV Cache Usage
说明:
推理系统还能容纳多少并发 sequence。
对于 inference capacity planning,后者更直接。
13. 第七层:Prefill / Decode 分阶段指标
如果系统能够采集,建议分别监控:
prefill latency
decode latency
prefill tokens/s
decode tokens/s
因为两个阶段的硬件行为不同。
13.1. Prefill
典型特点:
计算密集
矩阵大
Tensor Core utilization 高
因此更接近:
compute-bound。
13.2. Decode
典型特点:
单步计算规模较小
频繁读取KV Cache
HBM访问非常重要
更容易:
memory-bound。
如果:
Prefill慢
Decode正常
和:
Prefill正常
Decode慢
排障方向完全不同。
14. 第八层:GPU 硬件指标
这一层主要由 DCGM 等 GPU 管理与遥测组件提供数据。
推理服务至少应该关注:
| 硬件资源 | 指标 |
|---|---|
| GPU忙碌程度 | GPU Util |
| SM计算 | SM Active |
| Tensor Core | Tensor Active |
| 显存容量 | FB Used/Free |
| 显存带宽 | DRAM Active |
| GPU频率 | SM Clock |
| 显存频率 | Memory Clock |
| 功耗 | Power |
| 温度 | Temperature |
| Host-GPU通信 | PCIe RX/TX |
| GPU-GPU通信 | NVLink |
| 硬件健康 | ECC/Xid |
但是这里有一个非常重要的原则:
GPU 指标应该解释推理指标,而不能取代推理指标。
例如:
GPU Util = 95%
本身不是最终目标。
真正目标应该是:
TTFT正常
TPOT正常
tokens/s高
error rate低
GPU utilization 只是解释这些结果的底层指标。
15. 一个很典型的推理故障分析
假设:
TTFT ↑
TPOT 正常
GPU Util 60%
Queue Length ↑
KV Cache正常
可以推断:
Decode没有明显问题
GPU也没有打满
但是请求大量排队
更应该检查:
scheduler
batcher
并发限制
请求准入策略
而不是直接扩 GPU。
16. 另一个典型情况:Decode 性能下降
例如:
TTFT 正常
TPOT ↑
GPU Util 高
DRAM 高
Tensor 中低
HBM Used 高
非常符合:
Decode memory-bound。
原因是大量 KV Cache 数据需要从 HBM 读取。
这时候增加:
Tensor FLOPS
未必能显著提升性能。
而:
HBM bandwidth
可能更关键。
这也是为什么推理硬件选择不能只看 TFLOPS。
17. 第九层:模型级指标
如果一个集群运行多个模型:
Llama
Qwen
Embedding
Reranker
一定要在 metric labels 里至少保留:
model
version
instance
然后监控:
requests by model
tokens by model
latency by model
errors by model
GPU usage by model
例如:
sum by(model)(
rate(output_tokens_total[5m])
)
这样才能知道:
哪个模型正在消耗资源。
18. 模型版本必须作为维度
生产推理平台经常:
Model v1
↓
Model v2
如果上线新模型之后:
TTFT +30%
tokens/s -20%
但监控系统没有保存:
model_version
就很难进行版本对比。
所以建议至少保留:
model
model_version
deployment
19. 第十层:节点和系统指标
GPU 不是孤立工作的。
完整路径:
Network
↓
CPU
↓
RAM
↓
PCIe
↓
GPU
所以还需要 node-exporter / cAdvisor:
CPU utilization
CPU throttling
RAM
page fault
network throughput
network errors
disk I/O
例如:
GPU Util ↓
CPU 100%
Queue ↑
可能是:
tokenizer 或 CPU preprocessing 成为瓶颈。
而:
GPU Util ↓
CPU低
NIC RX满
可能是:
网络数据入口成为瓶颈。
20. 第十一层:Kubernetes 指标
如果运行在 Kubernetes,还需要:
Pod Ready
Pod Restart
OOMKilled
Pending
CPU throttling
GPU allocation
Deployment replicas
HPA状态
特别是:
desired replicas
available replicas
例如:
需要 20 个 inference replicas
实际只有 15 个 Ready
那么:
queue ↑
TTFT ↑
就很好解释了。
21. 第十二层:容量指标
推理运维不能只做故障监控,还必须做容量规划。
建议建立:
GPU capacity
GPU allocated
GPU idle
request concurrency
tokens/s capacity
queue saturation
KV cache saturation
尤其:
Max Concurrent Sequences
非常重要。
如果一个实例最大:
256 sequences
当前:
250
那么即使:
GPU Util只有70%
系统也可能已经接近容量上限。
因为瓶颈是:
KV Cache / scheduler capacity
而不是 compute。
22. 第十三层:成本指标
LLM 推理非常贵,所以生产平台通常最终都会关心:
Cost per request
Cost per 1M tokens
GPU hour
tokens / GPU second
一个很有价值的指标:
例如:
Deployment A
100k tokens / GPU-hour
Deployment B
250k tokens / GPU-hour
B 的资源效率明显更高。
这类指标适合:
- 不同模型对比
- 不同量化方案对比
- 不同 batch 参数对比
- 不同 GPU 型号对比
23. 缓存指标
推理服务还可能有多种 cache。
例如:
Prefix Cache
Prompt Cache
KV Cache
Model Cache
特别是 prefix caching。
如果多个请求:
System Prompt
相同,就可以复用前缀计算。
因此建议采集:
prefix cache hit
prefix cache miss
cache hit ratio
reused tokens
定义:
如果:
cache hit rate突然下降
可能导致:
Prefill负载增加
TTFT增加
GPU compute增加
这是一条非常典型的因果链。
24. 请求取消和中断也应该监控
流式 LLM 服务用户经常:
停止生成
关闭页面
网络断开
因此:
request_cancelled_total
client_disconnect_total
aborted_sequences
都值得监控。
因为请求已经取消却仍然占用 GPU:
GPU继续生成
就是纯资源浪费。
25. 建议按照 RED + USE + LLM 三套模型组织
可以把整个推理监控体系压缩成三个思维框架。
25.1. RED:服务层
Rate
Errors
Duration
也就是:
请求量
错误率
延迟
25.2. USE:资源层
Utilization
Saturation
Errors
例如 GPU:
Utilization → SM/Tensor/GPU Util
Saturation → HBM/KV Cache/Queue
Errors → ECC/Xid
25.3. LLM 专有指标
TTFT
TPOT
ITL
Input Tokens
Output Tokens
KV Cache
Prefill
Decode
Batch
这样结构就非常清楚。
26. 第一版监控系统的设计建议
第一版监控系统应优先覆盖以下指标,不必在初期采集数百个低价值指标。
| 层级 | 第一批核心指标 |
|---|---|
| 服务 | QPS、error rate、P95/P99 |
| 用户体验 | TTFT P95/P99、TPOT P95/P99 |
| 吞吐 | input tokens/s、output tokens/s |
| 请求 | input/output token length |
| 调度 | queue length、queue time |
| Batch | batch size、active sequences |
| KV Cache | used%、eviction/failure |
| GPU | Util、Tensor、DRAM、HBM |
| 硬件健康 | Temp、Clock、ECC、Xid |
| K8s | Pod Ready、Restart、Pending |
| 成本 | tokens/GPU-second |
仅仅这一套已经能覆盖大量生产问题。
27. Prometheus 指标命名可以这样设计
例如自己开发 inference exporter,可以设计:
llm_requests_total
llm_request_errors_total
llm_request_duration_seconds
llm_time_to_first_token_seconds
llm_time_per_output_token_seconds
llm_input_tokens_total
llm_output_tokens_total
llm_queue_requests
llm_queue_duration_seconds
llm_batch_size
llm_active_sequences
llm_kv_cache_usage_ratio
llm_kv_cache_evictions_total
llm_prefill_duration_seconds
llm_decode_duration_seconds
再通过 label 区分:
model
version
pod
node
gpu
namespace
例如:
llm_output_tokens_total{
model="qwen",
version="v3",
pod="inference-01"
}
28. 但一定要控制 Label Cardinality
这是推理监控系统非常容易犯的错误。
不要随便加:
request_id
user_id
prompt
session_id
到 Prometheus label。
例如:
request_id="abc123"
request_id="abc124"
request_id="abc125"
...
每个请求都会创建新时间序列,Prometheus 很快就会发生:
High Cardinality。
所以:
request_id
user_id
prompt
应该进入日志/Tracing 系统。
而 Prometheus label 应该主要保存低基数维度:
model
version
namespace
pod
node
gpu
status
这是推理监控设计里非常重要的一条原则。
29. Metrics、Logs、Tracing 应该分工
成熟推理系统不会什么都塞 Prometheus。
应该:
Observability
┌──────────┼──────────┐
│ │ │
Metrics Logs Traces
│ │ │
Prometheus Loki Tempo
Metrics:
系统现在有没有问题?
Logs:
具体报了什么?
Tracing:
一个请求到底慢在哪里?
例如:
TTFT P99 ↑
Metrics 发现问题。
然后 Trace:
Gateway 10ms
Queue 1200ms
Prefill 300ms
Decode 2000ms
马上发现:
Queue 是主要瓶颈。
30. 最终形成一棵推理故障诊断树
假设收到:
LLM 服务 P99 延迟升高。
第一步拆:
P99 ↑
│
├── TTFT ↑ ?
│
└── TPOT ↑ ?
如果:
TTFT ↑
继续:
Queue Time ↑ ?
│
├── 是 → Capacity / Scheduler
│
└── 否
│
└── Prefill ↑
│
├── Prompt变长?
├── GPU Tensor变慢?
└── Prefix Cache下降?
如果:
TPOT ↑
继续:
Decode慢
│
├── HBM/DRAM Active ↑
├── KV Cache ↑
├── SM Clock ↓
├── GPU straggler
└── NVLink/NCCL异常
这样:
用户体验指标 → 推理引擎指标 → GPU指标 → 硬件指标
就完全连起来了。
推理服务监控与普通微服务监控的主要区别是:最上层关注的不是 CPU,而是 token;核心 SLI 也不是 Pod Running,而是 TTFT、TPOT、tokens/s 和成功率。
关联文档
