Skip to content

vLLM 大模型推理服务:OpenAI 兼容 API 与启动参数调优

本页速览 用 vLLM 部署开源大模型(如 Qwen/Llama)并暴露 OpenAI 兼容 API 的实战:启动参数调优、量化模型加载、张量并行、压测与常见问题。

vLLM 大模型推理服务:OpenAI 兼容 API 与启动参数调优

一句话定义:vLLM 是一个基于 PagedAttention 与连续批处理(continuous batching)的高吞吐大模型推理引擎,一条命令就能把开源 LLM 部署成 OpenAI 兼容的 HTTP 服务

为什么值得动手:大模型推理和普通模型推理在工程上完全是两回事——KV Cache 的显存管理决定了你能不能扛住并发。朴素方案(比如把 Llama 装进 FastAPI 挨个推理)的吞吐低一个数量级,因为每个请求独占一块显存、串行执行。vLLM 用 PagedAttention 把 KV Cache 按页管理(见PagedAttention 论文精读),配合连续批处理,单卡就能把吞吐从个位数 QPS 提到几百 token/s。本文以 Qwen2.5-7B-Instruct 为例,走一遍完整部署、调参、压测流程。

一、vLLM 是什么,为什么快

三个核心技术:

  1. PagedAttention:把 KV Cache 切成固定大小的"页",按需分配,消除显存碎片与预分配浪费——显存利用率接近 100% 而非传统实现的 60%~80%;
  2. 连续批处理:传统批处理等一个 batch 全部生成完才释放资源;vLLM 逐 token 调度,某个序列生成完立即让位给新请求,GPU 永不空转;
  3. OpenAI 兼容 API:直接兼容 openai Python SDK,业务侧零改造接入。

一句话:vLLM 是当前单卡/多卡部署开源 LLM 的事实标准。底层的 KV Cache 与显存机制详见大模型推理优化

二、安装与模型准备

bash
# 安装(Python 3.9+)
pip install vllm          # 或按官方文档装对应 CUDA 版本

# 检查 GPU
nvidia-smi                # 确认显存与驱动,7B FP16 权重约 14GB + KV Cache

# 模型直接从 Hugging Face 拉取,首次会自动下载到 ~/.cache/huggingface
# 也可以先手动下载再指向本地路径
huggingface-cli download Qwen/Qwen2.5-7B-Instruct --local-dir ./Qwen2.5-7B-Instruct

硬件底线先交代:Qwen2.5-7B-Instruct FP16 权重约 14.6GB,单张 24GB 显存(如 A10/4090)是起步配置;要用 32B 以上模型或更大上下文,需要多卡或量化(见第六、七节)。

三、启动 OpenAI 兼容服务

bash
vllm serve Qwen/Qwen2.5-7B-Instruct \
  --gpu-memory-utilization 0.9 \
  --max-model-len 8192 \
  --tensor-parallel-size 1 \
  --dtype float16 \
  --served-model-name qwen2.5-7b \
  --port 8000

启动成功后默认在 http://localhost:8000/v1 暴露 OpenAI 兼容接口:/v1/chat/completions(对话)、/v1/completions(补全)、/v1/models(模型列表)。

显存估算公式

单卡可用 KV Cache 显存 ≈ GPU 总显存 × gpu-memory-utilization − 权重显存 − 激活开销。24GB 卡跑 7B FP16:24×0.9 − 14.6 ≈ 7GB KV Cache,约合 8192 上下文的并发序列 30~50 条(视实际 token 长度而定)。

四、关键启动参数详解

参数默认值作用调优建议
--gpu-memory-utilization0.9预留给 vLLM 的显存比例0.85~0.95;显存紧张时降到 0.8 保 KV Cache
--max-model-len模型默认(如 8192)单序列最大上下文长度过长浪费显存;业务用不到 32K 就设 8K
--tensor-parallel-size1张量并行卡数模型放不下时递增:2/4/8
--dtypeauto权重精度float16bfloat16,别用 float32(显存翻倍)
--quantizationNone量化后端(awq/gptq/…)见第七节量化加载
--enforce-eagerFalse跳过 CUDA Graph 编译启动慢/偶发编译报错时开,代价是吞吐略降
--enable-prefix-caching自动跨请求复用公共前缀的 KV Cache对话/Agent 场景强烈建议显式开启
--served-model-name模型 ID对外暴露的模型名换别名,业务不用改
--max-num-seqs256并发序列上限显存不足时调低,避免排队过多
--max-num-batched-tokens8192单步最多处理的 token 数小显存调小,防 OOM
--trust-remote-codeFalse允许加载自定义模型代码部分社区模型需要

顺序是"先保显存,再保吞吐"

--max-model-len--max-num-seqs--max-num-batched-tokens 三个参数共同决定显存预算。先看 --gpu-memory-utilization 分出的 KV Cache 够不够支撑目标并发,再逐项收紧,而不是一上来就拉满。

一个服务部署多个模型

vllm serve 支持一次挂多个模型(在同一个显存池里共享 KV Cache),适合"轻量模型+重模型混部":

bash
vllm serve \
  Qwen/Qwen2.5-7B-Instruct \
  Qwen/Qwen2.5-0.5B-Instruct \
  --served-model-name qwen-7b \
  --served-model-name qwen-0.5b \
  --gpu-memory-utilization 0.9 \
  --max-model-len 8192

客户端通过 model="qwen-7b"model="qwen-0.5b" 选择模型。同一实例多模型会互相抢占 KV Cache 显存,混部前先用下面的显存公式估算:7B + 0.5B 权重约 15.3GB,24GB 卡上留给两个模型共用的 KV Cache 只剩约 6GB,并发被摊薄。先给结论:混部适合"一个服务多条链路",不适合"两个都要高并发"——后者请拆成两个服务实例或加卡。

与服务编排:容器与 GPU 资源

生产环境通常不直接裸跑 vllm serve,而是放进容器由 K8s 托管:

bash
docker run --gpus all --shm-size 8g \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  -p 8000:8000 \
  vllm/vllm-openai:latest \
  --model Qwen/Qwen2.5-7B-Instruct \
  --gpu-memory-utilization 0.9 \
  --max-model-len 8192

注意 --shm-size:vLLM 依赖共享内存做 tokenizer 与数据传递,默认 64MB 会报 /dev/shm 不足——这是容器部署最常见的启动失败原因之一。K8s 里给容器申请 nvidia.com/gpu: 1,并配 liveness/readiness 探针打 /health 端点(vLLM 自带)。

五、客户端调用:OpenAI SDK 与流式输出

python
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",   # vLLM 的 OpenAI 兼容端点
    api_key="EMPTY",                        # vLLM 默认不校验 key
)

# 普通对话
resp = client.chat.completions.create(
    model="qwen2.5-7b",
    messages=[{"role": "user", "content": "用一句话解释什么是 KV Cache"}],
    max_tokens=256,
    temperature=0.7,
)
print(resp.choices[0].message.content)

# 流式输出:长回答场景务必用 stream,首 token 延迟显著更低
stream = client.chat.completions.create(
    model="qwen2.5-7b",
    messages=[{"role": "user", "content": "写一首关于模型部署的诗"}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

为什么 LLM 不用朴素 FastAPI 套

把 LLM 装进 FastAPI 挨个推理:一个请求占满整卡显存跑完整生成,其余请求排队,GPU 利用率 20% 都不到;流式输出还得自己搓 SSE。vLLM 已经内置了连续批处理、流式、限流、指标,业务层直接用 OpenAI SDK 对接。结论:LLM 场景不要自研朴素服务,直接上推理引擎。 完整对比见大模型推理优化

六、多卡张量并行

单卡放不下就用 --tensor-parallel-size 切分:

bash
# 用 2 张 24GB 卡跑 70B 量化模型,或用 4 张跑更大模型
vllm serve Qwen/Qwen2.5-72B-Instruct-AWQ \
  --tensor-parallel-size 4 \
  --gpu-memory-utilization 0.9 \
  --max-model-len 8192

三个要点:

  1. 卡间通信需要 NVLink/PCIe 直连,异构 GPU 混用会拖累整体(按最慢卡同步);
  2. tensor-parallel-size 必须整除注意力头数/层数的可切分维度,一般取 2/4/8;
  3. 张量并行收益有边际:2 卡吞吐约 1.7~1.9 倍,4 卡约 3~3.5 倍,不是线性。追求性价比的另一种路是单卡量化(下一节)。

七、量化模型加载

量化是把 7B 模型塞进更小显存、换更高吞吐的关键,原理见量化。AWQ/GPTQ 是主流选择:

bash
# AWQ 量化版:24GB 卡上 72B 也能跑
vllm serve Qwen/Qwen2.5-72B-Instruct-AWQ \
  --quantization awq \
  --gpu-memory-utilization 0.9 \
  --max-model-len 8192

# GPTQ 量化版
vllm serve TheBloke/Llama-2-7B-Chat-GPTQ \
  --quantization gptq \
  --max-model-len 4096

量化收益与代价的实测参考(7B 模型,单卡 A10,批处理吞吐):

精度权重显存相对吞吐质量影响
FP16~14.6GB1.0×(基准)
INT8~7.4GB约 1.2×极小
INT4 (AWQ/GPTQ)~4.1GB约 1.5~1.8×多数任务可接受,极端推理题略降

先给结论:显存是瓶颈就量化,不是就保持 FP16。INT4 模型质量损耗通常可接受,但涉及精确数学/推理类任务要做离线评测再定,别只看跑分。

八、压测:benchmark 工具与指标解读

vLLM 自带压测脚本,也可以直接用压测与容量规划里的方法:

bash
# 模拟 200 个并发请求,每个要求生成 256 token
python benchmarks/benchmark_serving.py \
  --model Qwen/Qwen2.5-7B-Instruct \
  --tokenizer Qwen/Qwen2.5-7B-Instruct \
  --request-rate 200 \
  --num-prompts 1000 \
  --max-tokens 256 \
  --save-result results.json

输出解读三个核心指标:

  • TTFT(Time To First Token):首 token 延迟。流式场景用户感知 = TTFT,目标 < 500ms~1s;
  • TPOT(Time Per Output Token):每个输出 token 的时间,等于 1/解码速度,越小越流畅;
  • 吞吐(Total token throughput):单位时间生成的 token 总数,同时区分输入与输出吞吐。

同配置下与朴素 Hugging Face transformers 部署的对照最能说明 vLLM 的价值(7B 模型、单卡 A10、并发 64、输出 256 token):

部署方式总吞吐 (token/s)每请求生成速度 (token/s)显存
transformers generate 串行约 300~600约 15~30(单请求)权重+单请求 KV
vLLM(连续批处理)约 3000~5000约 17~25/请求PagedAttention 按页分配

先给结论:vLLM 的吞吐来自"多个请求共享一次解码步",单请求速度并不比朴素部署快,快的是总量——所以它特别适合对话、Agent 这类多并发场景;单路超低延迟场景(单并发、每 token 15ms 内)该考虑更专门的优化(CUDA Graph、小模型)。

一组 7B/单卡参考数字(A10 24GB,并发 200):TTFT 约 300~800ms,TPOT 约 40~60ms/token(约 17~25 token/s/请求),总吞吐约 3000~5000 token/s。提高吞吐的三板斧:加大 --gpu-memory-utilization 留出更多 KV Cache、开 --enable-prefix-caching、量化。

常见问题与排查

问题现象排查
启动即 OOMCUDA out of memory / No available memory for the cache blocks--gpu-memory-utilization--max-model-len--max-num-seqs
KV Cache 不足日志 CacheConfig: gpu_memory_utilization... 报可用块不足给 KV Cache 更多显存;降并发上限
请求超长Input ... is longer than max-model-len调大 --max-model-len(注意显存)或提示客户端截断
并发上限请求排队、TTFT 飙升--max-num-seqs,调大并发或用更大 KV Cache
编译报错/启动极慢卡在 CUDA Graph 编译--enforce-eager 跳过,吞吐略降但稳定
模型返回 404model not found--served-model-name 与实际调用名不一致
前缀命中率低相同 system prompt 每次仍全量计算显式 --enable-prefix-caching,且前缀要做成公共部分

更多生产环境坑位见常见陷阱与反模式

延伸阅读

参考资料