深色模式
推理成本优化策略
摘要:本文面向要把 LLM 推理账单压下来的 SRE / 平台工程师。推理成本的核心杠杆不是"换更便宜的卡",而是提高每卡每元的 token 产出。围绕 vLLM(开源默认推理引擎),用 PagedAttention 削减 KV cache 浪费、连续批处理把 GPU 利用率从 30-40% 拉到 80%+、前缀缓存对 RAG / Agent 提速 30-50%、量化与投机解码进一步降本。所有吞吐数字来自公开基准,具体值随模型 / 版本 / 硬件变动,请在你自己的负载上复测并标注 [未实测]。
适用版本与前提
- vLLM(Apache 2.0,社区默认推理引擎;TensorRT-LLM / SGLang 为同类可选项)。
- 能拿到目标 GPU(A100 / H100 / L40S 等)与对应显存。
- 已具备 Prometheus(vLLM 原生暴露
/metrics)。
核心概念:推理成本 = 每 token 的卡时成本
text
每百万输出 token 成本 = GPU数量 × 裸单价(/小时) ÷ 吞吐(tokens/秒/卡) × 1e6 ÷ 36001
所以降成本两条路:降分子(更便宜的卡 / 更短占用)或涨分母(更高吞吐)。后者往往空间更大。
架构与优化杠杆
1. PagedAttention:先挤掉显存浪费
传统推理为每个请求预分配「最大可能长度」的连续 KV cache,浪费 60-80% 显存。PagedAttention 像操作系统虚拟内存一样把 KV cache 切成定长 block(默认 16 token)按需分配,浪费降到 <4%,从而支持更大并发批次 → 更高吞吐。
2. Continuous Batching(连续批处理)
静态批处理要等整批完成才进下一批,长尾请求让 31 个槽位空转。连续批处理在每个 token 步把已完成序列的槽位立即换入排队请求,GPU 利用率从 30-40% 提到 80%+。这是降本的最大单一杠杆。
3. Prefix Caching
上千请求共享同一 system prompt / RAG 文档时,朴素服务重复计算前缀 KV。vLLM 自动识别共享前缀并复用,RAG / 多轮 Agent 场景通常带来 30-50% 吞吐提升,无需改应用代码。
生产实践:vLLM 部署与调优
基础部署(显存与并发调优)
bash
# 高吞吐配置: 拉高显存利用率与最大并发序列数
vllm serve meta-llama/Llama-3-8B-Instruct \
--tensor-parallel-size 1 \
--gpu-memory-utilization 0.90 \
--max-num-seqs 256 \
--max-model-len 8192 \
--enable-prefix-caching \
--port 80001
2
3
4
5
6
7
8
2
3
4
5
6
7
8
bash
# 调用 (OpenAI 兼容 API)
curl -X POST "http://localhost:8000/v1/chat/completions" \
-H "Content-Type: application/json" \
--data '{
"model": "meta-llama/Llama-3-8B-Instruct",
"messages": [{"role":"user","content":"用一句话解释 GPU FinOps"}],
"max_tokens": 128
}'1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
关键参数取舍
--gpu-memory-utilization:越高能塞越多并发,但留太小会 OOM;生产常设 0.90。--max-num-seqs:并发上限,受显存与延迟目标约束;RAG 高并发可提到 512。--enable-prefix-caching:共享前缀负载(Agent / RAG)几乎必开。- 纯单流低延迟场景(batch size 1)PagedAttention 收益有限,此时可评估 TensorRT-LLM。
量化降低显存占用、提升吞吐
bash
# 用 AWQ 4-bit 量化模型, 显存约降 3.5x, 精度损失小
vllm serve "TheBloke/Llama-3-8B-AWQ" \
--quantization awq \
--gpu-memory-utilization 0.901
2
3
4
2
3
4
多卡大模型:Tensor Parallelism
bash
# 70B 级模型需多卡切分
vllm serve meta-llama/Llama-3-70B-Instruct \
--tensor-parallel-size 4 \
--dtype bfloat161
2
3
4
2
3
4
多卡通信开销
张量并行跨卡有 NVLink 通信开销,per-GPU 效率会略降;pipeline parallelism 利用率更低。只在大模型放不进单卡时才上 TP,否则单卡 + 量化更经济。
成本估算(带型号 / 数量 / 时长 / 单价 / 利用率)
示例:在 1× A100-40G 上以 --gpu-memory-utilization 0.9 跑 8B 模型做常驻推理。 假设公开刊例裸单价 ≈ $4.10/卡·小时 [未实测,区域/合约相关],连续批处理把 GPU 利用率拉到 80%,实测吞吐 ≈ 2000 tokens/s/卡 [未实测,随模型与批次变动]:
python
# inference_cost.py
price_per_gpu_hr = 4.10 # A100-40G 公开刊例, [未实测]
gpus = 1
util = 0.80 # 连续批处理后利用率
throughput_tps = 2000 # tokens/秒/卡, [未实测]
hours = 24 * 30
monthly_cost = price_per_gpu_hr * gpus * hours # 名义 $2952
# 每百万输出 token 成本
cost_per_1m = price_per_gpu_hr * gpus / (throughput_tps * 3600) * 1_000_000
print(f"月度名义: ${monthly_cost:,.0f}")
print(f"每百万输出token: ${cost_per_1m:,.2f} (利用率{util})")
# 若利用率仅 20%, 同等吞吐下成本×4 → 约 $0.71/百万token [未实测]1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
吞吐数字必须自己复测
上文 2000 tokens/s/卡 是公开基准量级,真实值取决于模型、上下文长度、批大小与 vLLM 版本。任何未在你负载上跑过的吞吐都标 [未实测],不要用它做采购 / 容量决策。
验证
bash
# 用 vLLM 原生 Prometheus 指标核对吞吐与 KV 利用率
curl -s http://localhost:8000/metrics | grep -E \
"vllm:throughput|vllm:gpu_cache_usage|vllm:num_requests"
# 前缀缓存命中率 (高并发共享前缀场景应显著>0)
curl -s http://localhost:8000/metrics | grep cache_hit1
2
3
4
5
6
2
3
4
5
6
回滚与清理
- 量化若有精度回归(数学 / 长尾任务),回退到 FP8 / BF16 全精度,或仅对不敏感模型量化。
- 调
--max-num-seqs过高导致 OOM:降低到能稳定运行的档位,配合--block-size调优。 - 模型权重缓存(HF cache / LMCache)占用磁盘,定期清理未用模型避免存储费。
故障排查
- 吞吐上不去:查
gpu_cache_usage是否打满(KV 不够 → 提显存利用率或降max-model-len);查是否开了enable_chunked_prefill[版本相关]。 - P99 延迟毛刺:连续批处理下长请求拖尾,设
--max-num-batched-tokens限制单步 token 数。 - 前缀缓存不命中:确认请求前缀确实一致(system prompt 相同),随机前缀场景该优化无效。
安全与合规
- 无限调用 / 循环防护(重点):推理端点按 token 计费且可被脚本无限循环调用,单个失控 Agent 能在几小时内烧掉整月预算。必须在网关层做:per-key 速率限制(RPS / 并发)、单请求
max_tokens硬上限、每日 token 预算配额、异常调用告警。结合 LLMOps 成本视角 做预算熔断。 - 量化模型用于监管 / 医疗等高风险场景前,需评估精度合规边界。
成本 / 性能权衡
- 量化(AWQ/FP8)显存降 3-4x、吞吐升,但有精度代价;先用 eval 集验证再上生产。
- 投机解码延迟降 1.5-3x 但增加草稿模型算力,仅在延迟敏感场景划算。
- H100 显存带宽 3.35 TB/s vs A100 2.0 TB/s,推理(带宽瓶颈)收益直接;但单价 3x,需按"每 token 成本"而非"每卡成本"决策(见 gpu-cost.md)。