本文记录如何使用 vLLM + Docker Compose 部署 Qwen3.8-27B-FP8,并针对双 GPU、长上下文、思考模式、Tool Calling、Prefix Cache、Chunked Prefill 等常用能力进行配置。
本文配置主要面向以下场景:
- Qwen3.8-27B-FP8
- vLLM OpenAI 兼容接口
- 双 GPU 张量并行
- Agent / Tool Calling
- 长上下文请求
- 多轮对话
- 流式输出
- 思考模式
- 高并发推理
一、Docker Compose 完整配置
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm-qwen3.8-27b
restart: "no"
# 使用宿主机共享内存,对多 GPU/NCCL 通信比较重要
ipc: host
ports:
- "8000:8000"
volumes:
- /home/AI/model:/models
environment:
PYTORCH_CUDA_ALLOC_CONF: expandable_segments:True
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids:
- "0"
- "1"
capabilities:
- gpu
command:
- --model
- /models/Qwen3.8-27B-FP8
- --served-model-name
- qwen3.8-27b
# 思考内容解析器
- --reasoning-parser
- qwen3
# Tool Call 解析格式
- --tool-call-parser
- qwen3_coder
# 开启自动选择工具
- --enable-auto-tool-choice
# 使用两张显卡进行张量并行
- --tensor-parallel-size
- "2"
# 最大上下文长度
# 32K = 32768
# 64K = 65536
# 128K = 131072
- --max-model-len
- "131072"
# vLLM 可使用的 GPU 显存比例
- --gpu-memory-utilization
- "0.6"
# 开启前缀缓存
- --enable-prefix-caching
# 强制 PyTorch Eager 模式
# 一般不建议开启,除非遇到兼容性问题或需要调试
#- --enforce-eager
# 禁用 vLLM Custom All Reduce,GPU 通信改走 NCCL
# 多 GPU 环境建议根据硬件实际测速决定是否开启
- --disable-custom-all-reduce
# 开启分块预填充
- --enable-chunked-prefill
# 单次调度最大 Token 数
# 建议根据业务测试 4096 / 8192 / 16384
#- --max-num-batched-tokens
#- "16384"
# KV Cache 数据类型
- --kv-cache-dtype
- auto
二、核心参数说明
1. --model
- --model
- /models/Qwen3.8-27B-FP8
指定模型所在目录。
Docker 中已经将:
/home/AI/model
挂载为:
/models
因此模型实际目录:
/home/AI/model/Qwen3.8-27B-FP8
在容器中对应:
/models/Qwen3.8-27B-FP8
2. --served-model-name
- --served-model-name
- qwen3.8-27b
定义 OpenAI API 中使用的模型名称。
之后调用:
POST /v1/chat/completions
时:
{
"model": "qwen3.8-27b"
}
而不需要传完整模型路径。
三、思考模式配置
--reasoning-parser qwen3
- --reasoning-parser
- qwen3
用于解析 Qwen3 系列模型返回的思考内容。
配置后,vLLM 可以将模型的推理内容从普通正文中拆分出来,例如在 OpenAI Compatible API 中通过对应的 reasoning 字段返回。
需要注意:
--reasoning-parser负责“解析思考内容”,并不代表每一个请求都会自动开启思考。
是否真正启用 Thinking,还取决于模型的 Chat Template 以及请求中是否传入对应的 Thinking 参数。
例如部分 Qwen 模型可以通过:
{
"chat_template_kwargs": {
"enable_thinking": true
}
}
控制是否开启 Thinking。
四、Tool Calling 配置
1. Tool Call Parser
- --tool-call-parser
- qwen3_coder
指定工具调用内容的解析器。
当模型生成 Tool Call 时,vLLM 会按照对应格式将模型输出解析成 OpenAI 风格的:
{
"tool_calls": [...]
}
对于 Agent、MCP、Function Calling 等场景非常重要。
2. 自动选择工具
- --enable-auto-tool-choice
允许模型自主判断:
- 是否需要调用工具
- 调用哪个工具
- 直接回答还是执行 Tool Call
如果业务中使用:
- ReactAgent
- MCP
- Function Calling
- Agent 工作流
通常建议开启。
五、双 GPU 张量并行
- --tensor-parallel-size
- "2"
表示使用两张 GPU 进行 Tensor Parallel。
例如:
device_ids:
- "0"
- "1"
对应:
GPU 0
GPU 1
模型参数会被拆分到两张 GPU 上共同进行计算。
常见配置
| GPU 数量 | tensor-parallel-size |
|---|---|
| 1 张 | 1 |
| 2 张 | 2 |
| 4 张 | 4 |
| 8 张 | 8 |
如果只有一张 GPU:
- --tensor-parallel-size
- "1"
或者直接不指定,使用默认配置。
六、最大上下文长度
- --max-model-len
- "131072"
这里配置:
131072 Tokens
即约 128K 上下文窗口。
常见配置:
| 上下文 | max-model-len |
|---|---|
| 8K | 8192 |
| 16K | 16384 |
| 32K | 32768 |
| 64K | 65536 |
| 128K | 131072 |
| 256K | 262144 |
需要特别注意:
max-model-len配置得越大,并不代表每次请求都会实际占满这么多 KV Cache,但会明显影响 vLLM 的 KV Cache 规划以及最大并发能力。
例如实际业务通常只有:
4K ~ 16K
上下文,那么即使模型支持 128K,也不一定必须配置到 128K。
生产环境通常应该根据真实业务在:
32768
65536
131072
之间进行权衡。
七、GPU 显存利用率
- --gpu-memory-utilization
- "0.6"
控制 vLLM 可以使用多少比例的 GPU 显存。
例如一张 80GB GPU:
80GB × 0.6 ≈ 48GB
vLLM 会在这个显存预算内安排:
- 模型权重
- KV Cache
- 推理运行所需显存
常见配置:
| 值 | 特点 |
|---|---|
| 0.5 ~ 0.6 | 比较保守 |
| 0.7 ~ 0.8 | 一般生产环境 |
| 0.85 ~ 0.9 | 更高 KV Cache / 并发 |
| > 0.9 | OOM 风险增加 |
默认值通常比较激进。
如果 GPU 只运行 vLLM,并且显存比较充足,可以逐步从:
0.6
→ 0.7
→ 0.8
→ 0.9
进行压力测试。
八、Prefix Caching 前缀缓存
- --enable-prefix-caching
开启 Prefix Caching 后,对于多个请求中完全相同的 Prompt 前缀,vLLM 可以复用已经计算完成的 KV Cache。
例如系统提示词:
System Prompt
↓
知识库说明
↓
工具说明
↓
Agent Prompt
↓
用户问题
如果前面的内容在多个请求中保持不变,那么后续请求就有机会直接复用已经计算好的前缀。
特别适合
- Agent
- 多轮聊天
- 超长 System Prompt
- 大量 Tool Schema
- 固定知识背景
- 重复 Prompt
- 多用户使用相同 Agent
主要收益是降低:
Prefill 时间
进而改善:
TTFT(Time To First Token)
也就是用户点击发送之后,“第一个字什么时候出现”。
九、Chunked Prefill 分块预填充
- --enable-chunked-prefill
普通 Prefill 模式下,一个超长 Prompt 可能一次占用大量 GPU 计算资源。
例如:
请求 A:60K Prompt
请求 B:2K Prompt
请求 C:1K Prompt
如果 A 长时间独占计算资源,B、C 的输出也可能被延迟。
开启 Chunked Prefill 后,大 Prompt 可以被拆成多个 Chunk 进行调度:
60K Prompt
↓
Chunk 1
Chunk 2
Chunk 3
Chunk 4
...
GPU 可以在:
长 Prompt Prefill
+
其他请求 Decode
之间更加灵活地调度。
主要改善:
- 并发情况下的调度公平性
- Decode 延迟
- ITL
- 整体吞吐
- 长请求对短请求的阻塞问题
因此对于:
Agent + 长上下文 + 多用户并发
场景,通常建议开启。
十、max-num-batched-tokens
配置示例:
- --max-num-batched-tokens
- "16384"
这个参数决定:
一个 Scheduler Step 最多能够调度多少 Token。
它是影响 vLLM:
TTFT
ITL
吞吐
GPU 利用率
非常重要的参数之一。
一般可以从以下几个值进行压测:
4096
8192
16384
参数较小
例如:
4096
通常更加偏向:
- Decode 请求
- 低 ITL
- 多请求公平性
但长 Prompt Prefill 需要拆成更多批次。
参数较大
例如:
16384
可以一次处理更多 Prefill Token。
更加偏向:
- 长 Prompt
- Prefill 吞吐
- GPU 利用率
但可能增加其他 Decode 请求等待时间。
因此不存在所有机器统一的“最佳值”。
建议实际测试:
4096
8192
16384
然后比较:
TTFT
ITL
TPS
并发吞吐
十一、--disable-custom-all-reduce
- --disable-custom-all-reduce
在 Tensor Parallel 场景中,两张 GPU 之间需要频繁进行 All Reduce 通信。
vLLM 自带了一套 Custom All Reduce 优化实现。
开启:
--disable-custom-all-reduce
之后,相当于:
禁用 vLLM Custom All Reduce
↓
主要使用 NCCL 通信
是否应该开启?
没有绝对答案。
它和服务器的:
- GPU 型号
- PCIe 拓扑
- NVLink
- NCCL
- 驱动版本
- CUDA 版本
都有关系。
因此双 GPU 环境建议分别测试:
开启
和:
关闭
然后比较实际:
tokens/s
TTFT
并发吞吐
哪种更快就使用哪种。
单卡环境
如果:
--tensor-parallel-size 1
只有一张 GPU,没有跨 GPU All Reduce。
因此这个参数基本没有实际影响。
十二、Eager 模式
#- --enforce-eager
默认情况下,vLLM 会尽量使用 CUDA Graph 等优化方式提高推理性能。
开启:
--enforce-eager
后强制使用 PyTorch Eager Mode。
优点:
- 调试方便
- 部分模型兼容性更好
- 遇到 CUDA Graph 问题时方便排查
缺点:
- 性能通常会有所下降
- GPU 调度开销增加
因此建议:
能正常运行就不要开启。
只有出现兼容性、CUDA Graph 或特殊模型问题时再考虑。
十三、KV Cache 数据类型
- --kv-cache-dtype
- auto
控制 KV Cache 使用的数据类型。
auto 表示由 vLLM 根据模型和运行环境自动选择。
KV Cache 是大模型长上下文和高并发情况下最重要的显存消耗之一。
粗略来说:
上下文越长
×
并发请求越多
=
KV Cache 显存消耗越大
某些硬件和模型还可以考虑使用更低精度 KV Cache,例如 FP8,从而进一步减少显存占用。
但是否适合开启,需要同时考虑:
- GPU 是否支持
- vLLM 版本
- 模型兼容性
- 精度影响
- 性能变化
如果没有明确需求:
--kv-cache-dtype auto
是比较稳妥的配置。
十四、PYTORCH_CUDA_ALLOC_CONF
environment:
PYTORCH_CUDA_ALLOC_CONF: expandable_segments:True
用于调整 PyTorch CUDA 内存分配策略。
expandable_segments:True 可以在部分场景下减少由于显存碎片导致的:
CUDA Out Of Memory
尤其是在:
- 长上下文
- 动态 Batch
- 请求长度差异较大
- 显存利用率较高
的情况下有一定帮助。
十五、为什么使用 ipc: host
ipc: host
让容器使用宿主机 IPC Namespace。
对于:
PyTorch
NCCL
多 GPU
共享内存
等场景通常比较重要。
如果 /dev/shm 太小,多 GPU 推理可能出现性能或稳定性问题。
因此 vLLM Docker 部署中通常建议:
ipc: host
十六、推荐配置思路
如果是:
2 × A100 80GB
+
Qwen3.8-27B-FP8
+
Agent
+
长上下文
+
多用户并发
可以首先使用:
--tensor-parallel-size 2
--max-model-len 131072
--gpu-memory-utilization 0.6
--enable-prefix-caching
--enable-chunked-prefill
--kv-cache-dtype auto
然后重点压测三个参数。
1. GPU Memory Utilization
测试:
0.6
0.7
0.8
0.9
观察:
KV Cache 容量
最大并发
OOM
2. max-num-batched-tokens
测试:
4096
8192
16384
观察:
TTFT
ITL
TPS
并发吞吐
3. Custom All Reduce
分别测试:
默认
和:
--disable-custom-all-reduce
观察双 GPU 实际:
tokens/s
因为不同服务器的 GPU 拓扑不同,实际结果可能差别很大。
十七、几个性能指标
调优 vLLM 时,不建议只关注:
tokens/s
至少应该同时观察以下指标。
TTFT
Time To First Token
从请求发送到收到第一个 Token 的时间。
主要受:
- Prompt 长度
- Prefill 性能
- 排队时间
- Prefix Cache
影响。
ITL
Inter Token Latency
连续两个输出 Token 之间的时间间隔。
它直接影响用户看到模型“打字”是否流畅。
TPS
Tokens Per Second
模型每秒生成多少 Token。
例如:
40 tokens/s
表示平均每秒输出约 40 个 Token。
Throughput
系统整体吞吐能力。
例如:
同时 10 个请求
时,总共每秒能够完成多少 Token。
对于生产环境而言:
单请求 TPS 高,不代表高并发性能一定好。
因此最终还是需要结合实际业务并发进行压测。
十八、启动服务
进入 docker-compose.yml 所在目录:
docker compose up -d
查看日志:
docker logs -f vllm-qwen3.8-27b
查看 GPU:
watch -n 1 nvidia-smi
十九、测试 OpenAI API
普通请求:
curl http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.8-27b",
"messages": [
{
"role": "user",
"content": "你好,请介绍一下自己"
}
],
"stream": false
}'
流式请求:
curl -N http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.8-27b",
"messages": [
{
"role": "user",
"content": "你好,请介绍一下自己"
}
],
"stream": true
}'
二十、总结
这套配置的核心思路可以概括为:
Tensor Parallel
↓
双 GPU 运行模型
Prefix Caching
↓
降低重复长 Prompt 的 Prefill 成本
Chunked Prefill
↓
减少长请求对其他请求的阻塞
max-num-batched-tokens
↓
平衡 TTFT、ITL 和吞吐
gpu-memory-utilization
↓
决定 KV Cache 和最大并发空间
reasoning-parser
↓
支持 Qwen Thinking 内容解析
tool-call-parser
↓
支持 Agent / Tool Calling
对于 Agent、RAG、多轮聊天和长上下文业务来说,优化重点通常并不是单纯追求最高的单请求 tokens/s,而是平衡:
TTFT
+
ITL
+
并发吞吐
+
KV Cache
+
GPU 显存利用率
最终配置应该根据服务器 GPU 拓扑和真实业务请求长度,通过压力测试确定,而不是简单照搬某一组固定参数。
讨论
评论