vLLM 吞吐、延迟与显存参数的调优方法。
vLLM 的性能由显存预算、KV Cache、批处理参数和并行策略共同决定。调优顺序通常是:先确认模型能稳定加载,再压测基线,最后逐项调整 max-num-seqs、max-num-batched-tokens、前缀缓存和并行度。
不要同时改多个参数;每次只动一项,记录 TTFT、TPOT/ITL、吞吐和错误率。
pip install -U vllm
按业务设置上下文和显存上限,启动一个可压测的基线:
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 --port 8000 \
--served-model-name qwen-7b \
--max-model-len 8192 \
--gpu-memory-utilization 0.90 \
--max-num-seqs 256 \
--max-num-batched-tokens 8192 \
--enable-chunked-prefill \
--enable-prefix-caching \
--api-key "$VLLM_API_KEY"
用官方 bench 子命令压测 OpenAI 兼容接口:
vllm bench serve \
--backend openai-chat \
--base-url http://localhost:8000 \
--endpoint /v1/chat/completions \
--model qwen-7b \
--dataset-name random \
--random-input-len 1024 --random-output-len 256 \
--num-prompts 500 --request-rate 20
观察排队、KV Cache 和首 token 延迟:
curl -s http://localhost:8000/metrics \
| grep -E 'vllm:(num_requests_running|num_requests_waiting|kv_cache_usage_perc|gpu_cache_usage_perc|time_to_first_token_seconds_bucket)'
多卡张量并行时同时调整显存和并发上限:
vllm serve Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 4 \
--max-model-len 16384 \
--gpu-memory-utilization 0.92 \
--max-num-seqs 128
KV Cache 估算(每 token 字节):
# bytes/token = 2 * layers * kv_heads * head_dim * dtype_bytes
# Llama-2-7B MHA bf16: 2 * 32 * 32 * 128 * 2 = 524288 B ≈ 0.5 MiB/token
# 8192 token 单请求约占 4 GiB;GQA 模型按 kv_heads 比例缩小
--max-model-len 超过显存能容纳的 KV Cache 时,服务启动阶段就 OOM;先按上面的公式估算,再决定是否加 TP。--gpu-memory-utilization 设到 0.98 会挤掉 CUDA graph、NCCL 缓冲和同卡监控进程;生产通常留 5% 到 10%。--max-num-seqs 过高会让 KV Cache 频繁抢占和换出,吞吐未必上升;过低则请求排队、GPU 空闲。--max-num-batched-tokens 过高会让长 prefill 独占计算,TPOT 抖动;过低则批处理不足,吞吐下降。--kv-cache-dtype fp8 能提高并发但可能降低长上下文精度;上线前用业务评测集对比。kv_cache_usage_perc 与 gpu_cache_usage_perc 可能只存在一个;先 grep vllm 看实际名称。--enforce-eager 排除 CUDA graph 影响,但它本身会降低吞吐,不要作为生产配置。合上页面,先回答,再展开对照。
num_requests_waiting 持续升高说明什么?2 × layers × kv_heads × head_dim × dtype_bytes 估算,32 层、32 个 KV 头、head_dim 128、bf16 时约 0.5 MiB/token;8k 上下文单请求约 4 GiB。GQA 模型按 KV 头数比例缩小。max-num-seqs、上下文长度和前缀缓存命中率,而不是只调大并发上限。