vLLM 是一个高吞吐的推理引擎,核心是 PagedAttention(把 KV cache 按页管理,减少显存碎片)和连续批处理(continuous batching,新请求可以插进正在跑的批次)。 它对外暴露 OpenAI 兼容接口,所以换过去只需要改客户端的 base_url。2026 年 10 月,我在一张 8G 显存的 RTX 4060 上用 Qwen2.5-7B 的 4bit 量化权重起服务,--max-model-len 4096、--gpu-memory-utilization 0.85,启动后显存占满但不 OOM。单请求时它和 Ollama 的体感差别不大;并发到 8 个请求时,Ollama 开始明显排队,vLLM 的总吞吐还在往上走——这就是连续批处理的实际价值。
上面是结论。上一篇写 Ollama + Open WebUI 时,定位是「一个人本地随便聊」;这篇解决的是「几个人同时用同一个模型」。

vLLM 和 Ollama 的本质区别是什么?
结论:Ollama 优化的是「装得上、跑得动、好切换模型」,vLLM 优化的是「单位时间服务更多 token」——前者偏体验,后者偏吞吐。
| 维度 | Ollama | vLLM |
|---|---|---|
| 目标场景 | 单机自用、快速试模型 | 多人共用、API 服务 |
| 调度方式 | 请求排队,逐批处理 | 连续批处理,动态插批 |
| 显存管理 | 整块分配 | PagedAttention 分页 |
| 模型格式 | GGUF 为主 | safetensors / AWQ / GPTQ |
| OpenAI 兼容 | 有 /v1 端点 |
原生支持,实现更完整 |
| 装起来的难度 | 一条命令 | 要处理 CUDA、依赖、显存参数 |
| 多卡 | 支持有限 | --tensor-parallel-size 原生 |
判断标准:如果同时用的人超过两个,或者你要给一个应用当后端,vLLM 值得折腾;如果只是自己写代码时补全、偶尔问两句,Ollama 更省事。
我两个都留着:Ollama 跑在 3060 那台机器上做日常实验,vLLM 跑在 4060 上给内部工具当接口。

第一步:装之前先算清楚显存
结论:7B 模型 4bit 量化权重约占 4.5G,剩下的显存才是 KV cache 的地盘——8G 卡能跑,但没有富余。
先做个粗算,避免装完才发现放不下:
| 项目 | 7B / 4bit | 说明 |
|---|---|---|
| 权重 | ~4.5 GB | 4bit 量化后约 0.6GB/1B 参数 |
| 激活与框架开销 | ~0.8 GB | CUDA context、临时张量 |
| KV cache 可用 | ~1.5–2.5 GB | 取决于 gpu-memory-utilization |
| 上下文长度 | 4096 起 | 8192 需要更大 KV 预算 |
KV cache 的大小和「层数 × 头数 × 头维度 × 序列长度 × 并发数」成正比。它不是一个固定值,而是随并发和上下文长度线性增长。 这就是为什么「明明权重才 4.5G,8G 卡却报显存不足」——吃显存的是 KV cache。
先确认显卡和驱动:
$ nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv
name, memory.total [MiB], driver_version
NVIDIA GeForce RTX 4060, 8188 MiB, 566.36
$ nvcc --version | tail -2
vLLM 对 CUDA 版本有要求,装之前对一眼官方 安装文档 里标注的对应关系,别装到一半才发现不匹配。

第二步:安装与下载权重
结论:用独立虚拟环境装,权重走国内镜像下——这两件事能省掉 80% 的安装时间。
$ python -m venv /opt/vllm-env
$ source /opt/vllm-env/bin/activate
$ pip install --upgrade pip
$ pip install vllm==0.6.3
版本号要写死。vLLM 迭代很快,参数名和默认值在不同版本之间有变化,pip install vllm 拿到最新版之后照着旧教程配参数会对不上。
下载模型(以 Qwen2.5-7B-Instruct 的 AWQ 版本为例):
$ export HF_ENDPOINT=https://hf-mirror.com
$ pip install huggingface_hub
$ huggingface-cli download Qwen/Qwen2.5-7B-Instruct-AWQ \
--local-dir /opt/models/qwen2.5-7b-awq
HF_ENDPOINT 这一行很关键。不设的话走 huggingface.co,国内经常卡在几百 KB/s 或者直接超时。镜像站是社区维护的,速度稳定在几十 MB/s。
下载完检查目录结构:
$ ls -lh /opt/models/qwen2.5-7b-awq
config.json generation_config.json model-00001-of-00002.safetensors tokenizer.json ...
config.json 里的 quantization_config 段会告诉 vLLM 这是 AWQ 权重,不用手动传 --quantization。

第三步:起服务,参数怎么给
结论:三个参数决定成败——--max-model-len(上下文长度)、--gpu-memory-utilization(显存占比)、--max-num-seqs(最大并发)。8G 卡上保守取值。
$ source /opt/vllm-env/bin/activate
$ vllm serve /opt/models/qwen2.5-7b-awq \
--served-model-name qwen2.5-7b \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096 \
--gpu-memory-utilization 0.85 \
--max-num-seqs 8 \
--dtype auto
逐个说:
--max-model-len 4096:单次请求的最大上下文。这个值直接决定 KV cache 的单请求占用,设 32768 在 8G 卡上必然起不来。--gpu-memory-utilization 0.85:vLLM 允许占用的显存比例。0.85 是给系统和显示输出留余量;设 0.95 在带桌面的机器上容易崩。--max-num-seqs 8:同时处理的请求数上限。设小了并发上不去,设大了 KV cache 不够会报错。--dtype auto:让 vLLM 自己判断,AWQ 权重会走对应的 kernel。
启动日志里会打印关键信息,这三行必须看:
INFO: Maximum concurrency for 4096 tokens per request: 5.83x
INFO: KV cache memory: 1.72 GiB
INFO: GPU blocks: 262, CPU blocks: 0
Maximum concurrency 是这套配置能同时服务多少个「满 4096 token」的请求。5.83x 意味着理论上能同时跑 5 个长请求,短请求能更多。这个数字比你猜的准。

第四步:用 OpenAI SDK 直接连
结论:vLLM 的 /v1/chat/completions 和 OpenAI 的协议一致,改 base_url 就能跑,连 api_key 都只是占位。
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="not-needed")
resp = client.chat.completions.create(
model="qwen2.5-7b",
messages=[{"role": "user", "content": "用三句话解释 PagedAttention"}],
temperature=0.7,
max_tokens=256,
)
print(resp.choices[0].message.content)
print(resp.usage)
api_key 是必填参数但 vLLM 默认不校验,随便填一个非空字符串即可。如果服务暴露在公网,必须加 --api-key 你的密钥,否则任何人都能白嫖你的卡。
服务端指定了 --api-key 之后,客户端改用:
client = OpenAI(base_url="http://你的域名/v1", api_key="你的密钥")
流式也一样,stream=True 直接可用,不用改别的东西:
$ curl -s http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen2.5-7b","messages":[{"role":"user","content":"你好"}],"stream":true}'
兼容端点的完整说明在 vLLM · OpenAI-Compatible Server,包括 /v1/models、/v1/embeddings、工具调用等。

第五步:并发到底差多少
结论:单请求没差别,并发上来差距明显——因为 Ollama 的请求是排队的,vLLM 是插批的。
我用同一份提示词、同一个模型规模做了对比,观察到的现象是:
| 场景 | Ollama | vLLM(8G / 7B AWQ) |
|---|---|---|
| 1 个请求 | 体感相当 | 体感相当 |
| 4 个并发 | 明显的排队感,后发的等前面的 | 基本同时出字 |
| 8 个并发 | 响应时间接近 4 倍 | 响应时间约 1.5–2 倍 |
| 显存表现 | 稳定,占用低 | 接近打满,靠分页调度 |
具体毫秒数会随提示词长度、生成长度、量化方式大幅波动,我不打算给一个「vLLM 快 X 倍」的数字——这个数字在不同硬件和不同请求形态下毫无可比性。可靠的结论是定性的:连续批处理在并发场景下的优势随并发数增长而放大,单请求时两者没有本质区别。
如果你的使用场景是「一个人用」,那 vLLM 的收益接近零,还多了安装成本。这也是我一直建议先用 Ollama 的原因。

踩过的三个坑
结论:三个坑全部和显存有关——上下文设太大、并发设太大、gpu-memory-utilization 设太高。
坑一:No available memory for the cache blocks。 这是最典型的报错,意思是权重加载完之后没有空间给 KV cache 了。三种改法按优先级:降 --max-model-len、降 --max-num-seqs、提 --gpu-memory-utilization(如果还有余量)。我一开始把 max-model-len 设成 16384,直接起不来,降到 4096 才过。
坑二:显存打满后系统卡死。 在带桌面的 Windows 上尤其明显——vLLM 按 gpu-memory-utilization 抢显存,桌面环境也需要显存合成画面,两边打架的结果是整机卡住。8G 卡带桌面时把比例降到 0.75 更稳;纯命令行环境可以到 0.9。
坑三:以为 AWQ 权重能直接喂给 Ollama。 不能。Ollama 要 GGUF,vLLM 要 safetensors/AWQ/GPTQ。两套格式要各自准备一份,别指望一个权重通吃。我最初的目录里混着两种格式,vllm serve 报了一堆看不懂的 tensor 名字错误,查了很久才发现指错了目录。
什么时候该换回 Ollama
结论:单人使用、频繁切模型、机器显存小于 8G,这三条命中任何一条,Ollama 都是更划算的选择。
vLLM 的真实成本不是安装,是调参——每换一个模型、改一次上下文长度,都要重新算一遍 KV cache 预算。这套东西适合「模型固定、长期对外服务」的场景。如果你的用法是「今天试试 Qwen、明天试试 Llama」,Ollama 的 ollama run 是无敌的。
还有一个现实问题:8G 显存跑 7B 4bit 已经是舒适区的边缘。想上 14B,要么换 12G 以上的卡,要么接受更短的上下文和更低的并发。
常见问题
Q:vLLM 支持 CPU 推理吗?
A:有 CPU 后端但吞吐很低,只适合验证流程。真正的 CPU 推理用 llama.cpp 更合适。
Q:能不能多卡?
A:支持,--tensor-parallel-size 2 用两张卡切分模型。要求卡型号一致、显存接近,否则会被最小的那张拖住。
Q:模型怎么换成别的?
A:把 vllm serve 后面的路径换掉,--served-model-name 一起改。上下文和并发参数要按新模型的规模重新算。
Q:能不能接 new-api 统一管理?
A:能,把 vLLM 当成一个 OpenAI 兼容的上游填进 new-api,就能和云端 API 混在一起按模型名路由。
Q:服务重启后模型要重新加载多久?
A:7B 从磁盘加载约 10–30 秒,取决于磁盘速度。放 NVMe 上会明显更快,这也是我把它装在系统盘而不是机械盘的原因。