vLLM与SGLang启动参数调优实战:从默认配置到生产级吞吐量翻倍——Agent推理引擎篇

预计阅读时间:20 分钟

专栏《人工智能Agent从部署到生产》第17篇:不换硬件、不动模型,只改启动参数,vLLM/SGLang 吞吐量从 500 token/s 提到 4600 token/s 的完整方法论。

TL;DR

vLLM 和 SGLang 的默认启动参数是「安全低保」——它能跑,但大概率只用了你 GPU 一半的潜力。本文用一套可复现的调参方法论,覆盖 GPU 显存分配、KV Cache 利用率、CUDA Graph 覆盖范围、并行策略选择、调度保守度 五大维度,给出不同场景(在线低延迟 / 离线高吞吐 / 长上下文 / 多轮对话)的推荐配置组合。

核心结论就三句话:

  1. 吞吐量的天花板是 KV Cache 大小——--gpu-memory-utilization(vLLM)和 --mem-fraction-static(SGLang)是你最优先要调的参数
  2. CUDA Graph 不是默认覆盖全批量范围的——增加 --cuda-graph-max-bs 到 512/768 往往带来 20-40% 的吞吐提升,代价是额外显存
  3. SGLang 比 vLLM 多一个「调度保守度」旋钮——--schedule-conservativeness 是 SGLang 独有的吞吐/稳定性平衡器

一、为什么默认参数不够:显存分配的三层蛋糕

先理解一个关键事实:GPU 显存不是全归模型的。两块推理引擎的内存分配模型相同:

┌────────────────────────────────────────────────┐
│               GPU 显存 (如 80GB H100)            │
├────────────────────────────────────────────────┤
│  ① 模型权重 (model weights)                      │
│     - 70B BF16 模型 ≈ 140GB (需跨多卡 TP)         │
│     - 8B BF16 模型 ≈ 16GB                        │
├────────────────────────────────────────────────┤
│  ② KV Cache 池 (KV cache pool)                  │
│     ← 这是吞吐量的天花板                          │
│     ← 越大 → 同时服务的请求越多                     │
├────────────────────────────────────────────────┤
│  ③ CUDA Graph 缓冲区                             │
│     ← --cuda-graph-max-bs 越大 → 占用越多          │
├────────────────────────────────────────────────┤
│  ④ 激活值/临时缓冲区 (activations + buffers)       │
│     ← 预填充阶段临时张量、PyTorch 分配器开销          │
└────────────────────────────────────────────────┘

调参的本质:在 ① 固定的前提下,尽可能把显存分配给 ②,同时保证 ③④ 不 OOM。

引擎 控制 ①+② 的参数 默认值 含义
vLLM --gpu-memory-utilization 0.90 ①+② 占总显存比例
SGLang --mem-fraction-static 自动计算 ①+② 占总显存比例

二、vLLM V1 五大核心参数逐一拆解

2.1 --gpu-memory-utilization(最优先调)

默认值: 0.90
建议范围: 0.80 ~ 0.95

这个参数控制 vLLM 预分配多少比例的 GPU 显存给「模型权重 + KV Cache」。数值越大,KV Cache 越大,能并发处理的请求越多。

但 V1 引擎的 warmup 阶段会在 max_num_seqs 个假请求上跑 sampler,如果设太高会 warmup 阶段就 OOM:

# 保守配置(几乎不会 OOM)
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --gpu-memory-utilization 0.85

# 激进配置(需要配合小 max-num-seqs)
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --gpu-memory-utilization 0.95 \
  --max-num-seqs 32

调优方法:先用 0.85 跑通,然后每次 +0.02,直到遇到 OOM 再 -0.02。这个「刚好不 OOM」的值就是你的最优解。

2.2 --max-num-seqs(并发请求上限)

默认值: 256
V1 建议范围: 32 ~ 128(普通模型)/ 4 ~ 16(DeepSeek-V3 等大模型)

这是 V0 → V1 迁移最大的坑:V1 的 max_num_seqs 不能照搬 V0 的值。V1 在 warmup 时为每个 seq 预分配采样器显存,所以 256 这个默认值在 V1 下极易 OOM。

# V1 安全启动(Llama-8B 单卡)
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --max-num-seqs 64

# V1 + DeepSeek-V3(8×H100)
vllm serve deepseek-ai/DeepSeek-V3 \
  --tensor-parallel-size 8 \
  --max-num-seqs 16 \
  --gpu-memory-utilization 0.85

判断是否需要调整:看日志里的 preemption 告警。

WARNING: Sequence group 0 is preempted by PreemptionMode.RECOMPUTE
because there is not enough KV cache space.
→ 降低 max-num-seqs 或提高 gpu-memory-utilization

preemption 次数越多 = 实际并发超出了 KV Cache 容量 = 请求被反复踢出再重算 = 延迟暴涨。

2.3 --max-model-len(最大上下文长度)

默认值: 模型理论最大值(如 128K)
建议值: 实际业务需求的最大值

这是新手最常犯的错误:不设 --max-model-len,vLLM 按模型 config.json 里的理论最大值预分配 KV Cache。一个声称支持 128K 上下文的模型,如果业务只需要 8K,设 128K 会浪费大量显存。

# ❌ 默认:按模型理论最大值预分配,浪费显存
vllm serve meta-llama/Llama-3.1-8B-Instruct

# ✅ 按实际业务需求限制
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --max-model-len 8192

实际效果:把 max_model_len 从 131072 降到 8192,KV Cache 可用容量可提升 2-4 倍(取决于模型架构)。

2.4 --max-num-batched-tokens(批处理 token 预算)

默认值: 与 max-model-len 一致
建议范围: 4096 ~ 16384

这是 Chunked Prefill 的核心控制参数。V1 默认启用 Chunked Prefill —— 调度器优先处理 decode 请求,用剩余 token 预算处理 prefill 分块。

效果 适用场景
2048 ~ 4096 ITL(Token 间延迟)最优,prefill 被切更碎 在线聊天,延迟敏感
8192 ~ 16384 TTFT(首 Token 延迟)最优,prefill 一次处理更多 离线批处理
= max-model-len 接近 V0 行为(但仍优先 decode) 简单迁移,不想调
# 延迟敏感型(聊天机器人)
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --max-num-batched-tokens 4096 \
  --max-num-seqs 128

# 吞吐优先型(文档批处理)
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --max-num-batched-tokens 16384 \
  --max-num-seqs 256

2.5 优化等级 -O 参数

vLLM V1 提供 4 级优化,控制启动时间与运行性能的权衡:

等级 CUDA Graph 行为 启动时间 运行吞吐
-O0 无 CUDA Graph 最快 最低
-O1 Piecewise CUDA Graph 较快 中等
-O2(默认) Full + Piecewise CUDA Graph 较慢 最高
-O3 暂同 -O2 同 -O2 同 -O2
# 开发调试用 -O0(秒级启动)
vllm serve model --optimization-level 0

# 生产用默认 -O2 即可
vllm serve model  # --optimization-level 2 是默认值

避坑-O0 下禁用 CUDA Graph 后吞吐会下降 30-50%,仅用于「我要快速测试模型能不能加载」的场景,不要在生产环境用。

2.6 并行策略速查

策略 参数 何时用
张量并行 --tensor-parallel-size N 模型放不进单卡
流水线并行 --pipeline-parallel-size N 跨节点超大模型
专家并行 --enable-expert-parallel MoE 模型(DeepSeek/Qwen3MoE)
数据并行 --data-parallel-size N 多副本提吞吐

关键认知:数据并行的吞吐扩展效率远高于张量并行。如果单卡能放下模型,用 8×DP 比 1×TP8 吞吐高得多。


三、SGLang 六大核心参数逐一拆解

SGLang 是 DeepSeek 官方推荐的推理引擎,它在 vLLM 的参数体系上多了几个独有的调优旋钮。

3.1 --mem-fraction-static(SGLang 版显存分配)

默认值: 自动计算(保守)
建议范围: 0.80 ~ 0.92

与 vLLM 的 --gpu-memory-utilization 同概念,但 SGLang 的自动推断偏保守。看服务器启动日志:

max_total_num_tokens=665690, chunked_prefill_size=8192,
max_prefill_tokens=16384, max_running_requests=4096,
context_len=65536, available_gpu_mem=13.50 GB

判断标准: - available_gpu_mem 在 5-8 GB → 刚好,不用调 - available_gpu_mem > 10 GB → 太保守,提高 --mem-fraction-static - available_gpu_mem < 5 GB → 太激进,降低 --mem-fraction-static

# 如果日志显示 available_gpu_mem=13.50 GB(太保守)
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-R1 \
  --tp 8 \
  --mem-fraction-static 0.90  # 从默认值提高

3.2 --schedule-conservativeness(SGLang 独有,最重要)

默认值: 1.0
建议范围: 0.3(激进) ~ 1.5(保守)

这是 SGLang 区别于 vLLM 的最大特色。它控制调度器在接受新请求时的「冒险程度」。

看 SGLang 的运行时日志:

Decode batch. #running-req: 233, #token: 370959,
token usage: 0.82, cuda graph: True,
gen throughput (token/s): 4594.01, #queue-req: 317
指标 含义 健康范围
token usage KV Cache 利用率 > 0.9
#queue-req 排队请求数 100 ~ 2000
#running-req 正在处理的请求 接近 --max-running-requests

诊断决策树

token usage < 0.9 且 #queue-req > 0
  → 调度器太保守,KV Cache 没用满,请求在排队
  → 降低 --schedule-conservativeness 到 0.3

token usage 接近 1.0 且频繁出现:
  "KV cache pool is full. Retract requests."
  → 调度器太激进,频繁踢请求重算
  → 提高 --schedule-conservativeness 到 1.3
# 离线批处理(吞吐优先,激进调度)
python3 -m sglang.launch_server \
  --model-path Qwen/Qwen2.5-72B-Instruct \
  --tp 4 \
  --schedule-conservativeness 0.3 \
  --mem-fraction-static 0.90

# 在线服务(延迟优先,保守调度)
python3 -m sglang.launch_server \
  --model-path Qwen/Qwen2.5-72B-Instruct \
  --tp 4 \
  --schedule-conservativeness 1.3 \
  --max-running-requests 128

3.3 --cuda-graph-max-bs(CUDA Graph 批量覆盖)

默认值: 160 ~ 256(视模型而定)
建议范围: 256 ~ 768

CUDA Graph 把一系列 CUDA kernel 调用录制下来重放,消除逐 kernel 提交的开销。默认只覆盖小批量——如果你的实际并发经常超过 256,增加这个值可以显著提吞吐。

# 大 TP 推理场景(如 TP=8)扩大 CUDA Graph 覆盖
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-R1 \
  --tp 8 \
  --cuda-graph-max-bs 512 \
  --mem-fraction-static 0.85  # CUDA Graph 吃显存,需同步调低

CUDA Graph + torch.compile 叠加效果(DeepSeek-V3, batch_size=1, 256 input / 32 output tokens):

配置 总延迟 吞吐 (token/s)
无优化 7.322 s 39.34
CUDA Graph 1.256 s 229.27
CUDA Graph + torch.compile 1.011 s 284.86

从 39 token/s 到 285 token/s,纯靠启动参数,不换硬件不动模型。

3.4 --max-running-requests(并发上限)

默认值: 自动计算
建议范围: 取决于显存

与 vLLM 的 --max-num-seqs 对应。如果出现 OOM:

OOM 类型 调整方向
Prefill 阶段 OOM 降低 --chunked-prefill-size 到 4096 或 2048
Decode 阶段 OOM 降低 --max-running-requests
通用 OOM 降低 --mem-fraction-static 到 0.80
# 长上下文场景:小 chunk、少并发、大 KV Cache
python3 -m sglang.launch_server \
  --model-path meta-llama/Llama-3.1-8B-Instruct \
  --context-length 32768 \
  --chunked-prefill-size 4096 \
  --max-running-requests 64 \
  --mem-fraction-static 0.88

3.5 --tp-size vs --dp-size(并行策略)

SGLang 把张量并行和数据并行分开暴露:

# 数据并行优先(吞吐最大化):单卡放得下模型时
python3 -m sglang.launch_server \
  --model-path Qwen/Qwen2.5-7B-Instruct \
  --dp-size 8  # 8 个副本,8× 吞吐

# 张量并行(模型放不下时)
python3 -m sglang.launch_server \
  --model-path Qwen/Qwen2.5-72B-Instruct \
  --tp-size 4  # 4 卡拼一个模型

# DeepSeek 专用:DP Attention(MLA 架构关键优化)
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-R1 \
  --tp-size 8 \
  --dp-size 8 \
  --enable-dp-attention

DP Attention 的原理:MLA(Multi-head Latent Attention)的 KV Cache 只有 1 个 head,TP 无法切分,每卡存一份完整 KV Cache。开启 --enable-dp-attention 后,请求按 DP 维度分布,每张卡只维护自己那份请求的 KV Cache,显存效率大幅提升。

3.6 SGLang 专属加速选项

参数 适用场景 代价
--enable-torch-compile 小模型 + 小批量 首次启动编译时间 + 显存
--quantization fp8 支持 FP8 的模型 精度微降
--enable-flashinfer-mla DeepSeek 模型 需装 flashinfer
--speculative-algo NEXTN DeepSeek-V3/R1 需加载 draft 模型
--schedule-policy lpm 共享前缀多的场景 调度开销
--enable-hierarchical-cache 长上下文场景 需配置存储后端
# DeepSeek-R1 性能全开配置(8×H200)
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-R1 \
  --tp 8 \
  --trust-remote-code \
  --enable-dp-attention \
  --dp-size 8 \
  --cuda-graph-max-bs 512 \
  --mem-fraction-static 0.85 \
  --enable-flashinfer-mla \
  --enable-torch-compile \
  --torch-compile-max-bs 32 \
  --speculative-algo NEXTN \
  --speculative-draft SGLang/DeepSeek-V3-NextN \
  --speculative-num-steps 2 \
  --speculative-eagle-topk 4 \
  --speculative-num-draft-tokens 4

四、vLLM vs SGLang 参数对照速查表

调优维度 vLLM 参数 SGLang 参数 说明
显存分配 --gpu-memory-utilization --mem-fraction-static 越高吞吐越大,但越容易 OOM
并发上限 --max-num-seqs --max-running-requests V1 不能用 V0 的 256
批处理 Token --max-num-batched-tokens --chunked-prefill-size 小值=低延迟,大值=高 TTFT
上下文长度 --max-model-len --context-length 按实际需求设,别用理论最大值
CUDA Graph -O 优化等级控制 --cuda-graph-max-bs SGLang 可独立调整批量覆盖
张量并行 --tensor-parallel-size --tp-size 模型放不进单卡时用
数据并行 --data-parallel-size --dp-size 吞吐扩展首选
调度策略 N/A(固定) --schedule-conservativeness SGLang 独有
前缀调度 自动 prefix caching --schedule-policy lpm SGLang 需显式开启
CPU NUMA --numa-bind N/A vLLM 独有
torch.compile -O 等级内包含 --enable-torch-compile SGLang 需显式开启

五、三种典型场景的推荐配置

场景 A:在线聊天/Agent 服务(低延迟优先)

目标:P95 延迟 < 1s,ITL < 50ms

vLLM 配置(Llama-3.1-8B,单卡 H100):

vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.85 \
  --max-num-seqs 64 \
  --max-num-batched-tokens 4096 \
  --optimization-level 2

SGLang 配置

python3 -m sglang.launch_server \
  --model-path meta-llama/Llama-3.1-8B-Instruct \
  --context-length 8192 \
  --mem-fraction-static 0.85 \
  --max-running-requests 128 \
  --cuda-graph-max-bs 256 \
  --schedule-conservativeness 1.2 \
  --attention-backend fa3

场景 B:离线文档批处理(吞吐优先)

目标:最大化 token/s,延迟可以妥协

vLLM 配置(Qwen2.5-72B,4×H100):

vllm serve Qwen/Qwen2.5-72B-Instruct \
  --tensor-parallel-size 4 \
  --max-model-len 32768 \
  --gpu-memory-utilization 0.92 \
  --max-num-seqs 256 \
  --max-num-batched-tokens 16384 \
  --optimization-level 2

SGLang 配置

python3 -m sglang.launch_server \
  --model-path Qwen/Qwen2.5-72B-Instruct \
  --tp-size 4 \
  --context-length 32768 \
  --mem-fraction-static 0.90 \
  --max-running-requests 4096 \
  --chunked-prefill-size 16384 \
  --cuda-graph-max-bs 512 \
  --schedule-conservativeness 0.3

场景 C:DeepSeek-V3/R1 生产部署

目标:在 8×H200 上跑起来且不 OOM

# SGLang(DeepSeek 官方推荐引擎)
python3 -m sglang.launch_server \
  --model-path deepseek-ai/DeepSeek-R1 \
  --tp 8 \
  --trust-remote-code \
  --enable-dp-attention \
  --dp-size 8 \
  --mem-fraction-static 0.85 \
  --cuda-graph-max-bs 512 \
  --max-running-requests 256 \
  --chunked-prefill-size 8192 \
  --context-length 32768 \
  --enable-flashinfer-mla

# vLLM(备选,V1 引擎)
vllm serve deepseek-ai/DeepSeek-R1 \
  --tensor-parallel-size 8 \
  --max-model-len 32768 \
  --gpu-memory-utilization 0.80 \
  --max-num-seqs 16 \
  --max-num-batched-tokens 8192 \
  --enable-expert-parallel

六、调参方法论:四步走

第一步:跑通基准

先用保守参数把模型跑起来,记录基线吞吐:

# vLLM 压测
python3 -m vllm.benchmarks.serve \
  --model your-model \
  --dataset-name random \
  --random-input-len 1024 \
  --random-output-len 256 \
  --num-prompts 500

# SGLang 压测
python3 -m sglang.bench_serving \
  --backend sglang \
  --dataset-name random \
  --random-input 1024 \
  --random-output 256 \
  --num-prompts 500 \
  --host 127.0.0.1 --port 30000

第二步:最大化 KV Cache

逐步提高 --gpu-memory-utilization / --mem-fraction-static,每次 +0.02,压测一轮,直到出现 OOM 再回退 0.02。这是投入产出比最高的单步操作。

第三步:扩大 CUDA Graph 覆盖

--cuda-graph-max-bs 从默认翻倍(如 256→512),同时将显存分配参数下调 0.02-0.03(因为 CUDA Graph 缓冲区吃显存)。对比吞吐变化。

第四步:场景化微调

根据你的场景选型:

  • 在线服务 → 关注 P95 延迟,降低 max-num-seqs/max-running-requests
  • 离线批处理 → 关注 token/s,提高并发上限 + 激进调度(SGLang 降低 conservativeness)
  • 长上下文 → 设实际 max-model-len,降低 chunked-prefill-size

七、常见踩坑汇总

现象 修复
V1 默认 max-num-seqs=256 warmup OOM 降到 32-64
max-model-len 用理论最大值 KV Cache 极小、频繁 preemption 设为实际业务需求值
CUDA Graph 没覆盖实际批量 日志 cuda graph: False,吞吐偏低 提高 --cuda-graph-max-bs
SGLang schedule-conservativeness 默认值 KV Cache 利用率 < 0.9 且排队多 降到 0.3
DeepSeek 没开 DP Attention 每卡存一份完整 KV Cache,显存浪费 --enable-dp-attention --dp-size 8
多 socket 服务器跨 NUMA GPU 间通信延迟高 vLLM 加 --numa-bind
CPU 核心不够(<2+N) GPU 利用率低 vLLM 至少 2+N 物理核心(N=GPU 数)
开了 speculative decoding 但没配参数 启动失败 SGLang 必须同时配 --speculative-draft

八、总结

调参的本质是显存在四个池子之间做权衡。优先级从高到低:

  1. 设对 max-model-len/context-length——这是最容易白捡的显存
  2. 调高显存分配比例——从默认值往上探,找到 OOM 临界点
  3. 扩大 CUDA Graph 覆盖——从默认 256 提到 512/768
  4. 场景化微调并发和调度——在线降并发、离线提并发、SGLang 调 conservativeness
  5. 按需加加速选项——FP8 量化、torch.compile、speculative decoding

记住:不换硬件、不动模型、只改启动参数,吞吐量翻 3-5 倍是完全可行的。 上面的 CUDA Graph 基准就是证据:DeepSeek-V3 从 39 token/s 到 285 token/s,靠的只是几个 flag。


本文由 admin 原创,转载请注明出处。

相关推荐

评论

0
暂无评论,来发表第一条评论吧

发表评论

登录 后发表评论

发现更多