vLLM vs Ollama:高并发大模型推理部署与性能调优实战 📅 发布时间:2026/9/19 15:18:38 👁 浏览次数: 1. 为什么我最终选择了 vLLM 而不是 Ollama1.1 从一次压测数据说起去年年底我接手了一个内部知识库问答系统的搭建任务模型选的是 Qwen 系列的中等规模版本硬件是一台单机四卡的推理服务器。最开始为了快速跑通流程我用 Ollama 做了第一版部署交互式对话体验确实不错拉个模型、跑个run命令就能聊起来对新手极其友好。但问题很快就暴露了当我把并发请求从 1 路逐步加到 16 路、32 路的时候吞吐量几乎是一条平线延迟却像坐了火箭一样往上窜。单路生成速度大概 30 tokens/s加到 8 路并发时每路掉到 5 tokens/s 都不到总吞吐也就 40 tokens/s 左右GPU 利用率在nvidia-smi里看着只有 30% 上下晃悠显存倒是吃得挺满。这个现象其实很典型。Ollama 底层默认走的是 llama.cpp 那一套它的设计目标是让个人开发者在一台机器上轻松跑起来而不是让一台机器扛住尽可能多的并发请求。它的调度策略、KV Cache 管理方式、批处理能力都是围绕单用户或少量用户场景优化的。当我需要的是一个服务端扛住几十上百路并发的时候这套架构就成了瓶颈。后来我换成了 vLLM同样的模型、同样的硬件在 32 路并发下总吞吐直接冲到了 900 tokens/s 以上单路延迟也稳定在可接受范围内。这个差距不是一点半点标题里说的性能提升 23 倍并不是夸张的营销话术而是在特定并发场景下真实可以复现的数量级差异。当然这个倍数高度依赖于你的并发量、模型大小、序列长度和硬件配置不能当成一个固定值来理解但它背后的原理是扎实的。1.2 vLLM 到底解决了什么问题要理解 vLLM 为什么快得先理解大模型推理时显存是怎么被吃掉的。模型权重本身占一块这部分是固定的剩下的大头是 KV Cache也就是注意力机制里为了不重复计算历史 token 而缓存下来的键值对。传统做法是给每个请求预分配一块连续的显存空间按最大可能长度来留结果就是大量显存被浪费在预留但用不到的空间上同时因为碎片化能同时处理的请求数被死死卡住。vLLM 的核心创新叫PagedAttention思路直接借鉴了操作系统的虚拟内存分页管理。它把 KV Cache 切成固定大小的块block按需分配不要求连续。这样一来显存利用率能从传统方案的百分之三四十提升到百分之九十以上同样一块卡能塞下的并发请求数翻了好几倍。请求数上去了GPU 的计算单元才真正被喂饱吞吐自然就上来了。另一个关键机制是连续批处理Continuous Batching。传统批处理要等一个批次里所有请求都生成完才能开始下一批短请求被长请求拖死。vLLM 的做法是每个解码步都重新组批谁生成完了谁就退出新来的请求立刻补位。这个调度策略让 GPU 几乎不会空转尤其适合请求长度参差不齐的真实业务场景。所以 vLLM 的定位很清晰它不是给你做本地聊天玩具的它是给你做推理服务的。如果你的场景是我一个人在笔记本上跟模型聊聊天Ollama 完全够用甚至更省心但如果你的场景是我要对外提供一个 API扛住几十路并发还要控制成本那 vLLM 就是绕不开的选择。这也是为什么热词里vllm 单机多卡部署sglang 和 vllm这类词搜索量一直很高——大家都是在真实业务里被并发问题教育过的人。1.3 适合谁来读这篇内容这篇内容我假设你满足以下条件中的大部分手里有一块或几块 NVIDIA 显卡想在本地或内网环境把大模型跑成一个可调用的服务已经试过 Ollama 或 LM Studio 这类工具但对并发性能不满意对 Linux 命令行不陌生能看懂pip install和docker run希望有一套可以直接抄作业的部署流程而不是零散的官方文档片段。如果你完全是新手连 CUDA 驱动都没装过我建议你先用 Ollama 把模型跑起来找找感觉再回来看这篇。如果你已经在用 vLLM 但总觉得性能没调到位那第 3 章和第 4 章的参数调优和排查部分应该对你有用。下面我按环境准备 → 部署实操 → 参数调优 → 问题排查的顺序展开每一步都给出我实际用过的命令和踩过的坑。2. 部署前的环境准备与硬件选型2.1 硬件配置怎么选才不浪费钱先说结论vLLM 的性能对硬件非常敏感尤其是显存容量和显存带宽。我见过太多人拿一张消费级卡硬跑大参数模型结果要么 OOM显存溢出要么速度慢到怀疑人生然后回头骂 vLLM 不好用。其实问题出在硬件和模型不匹配。显存容量的估算有个粗略公式模型权重显存 ≈ 参数量 × 精度字节数。FP16 精度下每个参数占 2 字节INT8 占 1 字节INT4 占 0.5 字节。一个 7B 模型 FP16 大概需要 14GB 权重显存加上 KV Cache 和框架开销实际要留出 20GB 以上才舒服。13B 模型 FP16 就要 26GB 权重单张 24GB 卡根本放不下必须量化或者多卡。模型规模FP16 权重显存INT8 权重显存INT4 权重显存推荐最低显存7B~14GB~7GB~3.5GB16GB13B~26GB~13GB~6.5GB24GB32B~64GB~32GB~16GB48GB70B~140GB~70GB~35GB80GB显存带宽决定了 token 生成速度的上限。大模型推理是典型的显存带宽瓶颈任务每生成一个 token 都要把整个模型权重读一遍。所以 A100 的 80GB HBM2e带宽约 2TB/s和 RTX 4090 的 24GB GDDR6X带宽约 1TB/s在跑同样模型时速度差距会非常明显。这也是为什么数据中心卡贵得离谱但企业还是买——单位 token 成本算下来反而更低。我的建议是先确定你要跑的模型再倒推硬件。如果只是跑 7B 级别的模型做内部工具一张 4090 或 3090 就够了如果要跑 32B 以上要么上多卡要么老老实实做量化。热词里vllm 纯 cpu 模式也有人搜我得说清楚vLLM 确实支持 CPU 推理但速度跟 GPU 完全不是一个量级只适合验证流程或极低并发场景别指望它扛生产流量。2.2 软件栈的版本匹配是最大的坑vLLM 的版本迭代非常快而它跟 CUDA、PyTorch、显卡驱动之间的版本依赖关系又特别紧。我踩过最惨的一次坑是显卡驱动版本太老装完 vLLM 一启动就报 CUDA 相关的错排查了大半天才发现是驱动没跟上。正确的准备顺序是这样的先确认显卡驱动版本。用nvidia-smi看右上角的 CUDA Version这个数字表示你的驱动最高支持的 CUDA 版本不是已安装的版本。比如显示 12.4那你能装的 CUDA 运行时不能超过 12.4。再确定 PyTorch 版本。去 PyTorch 官网查它对应的 CUDA 版本选一个不超过驱动上限的。最后装 vLLM。vLLM 官方 wheel 包会绑定特定版本的 PyTorch 和 CUDA直接用 pip 装通常最省事。# 第一步查看驱动和 CUDA 支持上限 nvidia-smi # 第二步确认 Python 版本vLLM 要求 3.9 以上推荐 3.10 或 3.11 python --version # 第三步创建独立虚拟环境避免污染系统环境 python -m venv vllm-env source vllm-env/bin/activate # 第四步安装 vLLM会自动拉取匹配的 PyTorch pip install vllm注意不要手动先装 PyTorch 再装 vLLM很容易出现版本冲突。让 vLLM 的依赖解析器自己决定 PyTorch 版本除非你有明确的定制需求。如果你用的是 WSL2 环境热词里vllm 0.29 wsl2就是这个场景有几个额外注意点WSL2 的显存是动态分配的默认上限是系统内存的一半跑大模型前要在.wslconfig里调大memory和swap另外 WSL2 对多卡的支持不如原生 Linux 完善单卡场景问题不大多卡建议直接用原生系统。2.3 模型从哪里来、怎么放vLLM 加载模型支持两种方式直接从 Hugging Face 在线拉取或者指定本地路径。生产环境我强烈建议先把模型下载到本地原因有三一是避免每次启动都联网校验二是内网环境可能根本连不上外网三是本地路径加载速度更快、更可控。下载模型用huggingface-cli最方便pip install huggingface_hub # 下载模型到指定目录 huggingface-cli download Qwen/Qwen2.5-7B-Instruct --local-dir /data/models/qwen2.5-7b如果国内网络拉取慢可以配置镜像源环境变量这里指的是模型下载源的镜像不是网络代理export HF_ENDPOINThttps://hf-mirror.com模型目录的结构要确认一下标准的 Hugging Face 格式应该包含config.json、tokenizer.json、*.safetensors权重文件等。如果下载不完整vLLM 启动时会报找不到文件的错。我一般下载完会ls -lh看一眼权重文件大小对不对7B 的 FP16 模型 safetensors 加起来应该在 14GB 左右。3. vLLM 服务部署的完整实操流程3.1 最简启动命令与参数解读vLLM 装好之后启动一个 OpenAI 兼容的 API 服务只需要一行命令python -m vllm.entrypoints.openai.api_server \ --model /data/models/qwen2.5-7b \ --served-model-name qwen2.5-7b \ --host 0.0.0.0 \ --port 8000 \ --dtype auto \ --max-model-len 8192 \ --gpu-memory-utilization 0.9逐个参数说清楚它们的作用因为这几个参数直接决定了服务能不能起来、性能好不好--model模型路径可以是本地目录也可以是 Hugging Face 上的模型 ID。--served-model-name对外暴露的模型名称客户端调用时用的就是这个。不指定的话默认用路径路径长了调用很别扭。--host 0.0.0.0监听所有网卡这样内网其他机器才能访问。只在本机用的话写127.0.0.1更安全。--port服务端口默认 8000被占用就换一个。--dtype auto自动选择精度。如果模型是 FP16 就用 FP16是 BF16 就用 BF16。手动指定float16或bfloat16也行但auto最省心。--max-model-len最大上下文长度。这个值直接决定 KV Cache 要占多少显存设太大容易 OOM设太小长文本会被截断。要根据模型本身支持的长度和你的显存来权衡。--gpu-memory-utilization 0.9允许 vLLM 使用 90% 的显存。留 10% 给系统和其他进程设成 1.0 有时候会因为显存碎片导致启动失败。启动成功后终端会打印一堆日志看到Uvicorn running on http://0.0.0.0:8000就说明服务起来了。这时候可以用 curl 测一下curl http://localhost:8000/v1/models返回模型列表就说明 API 正常。再发一个对话请求curl http://localhost:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: qwen2.5-7b, messages: [{role: user, content: 用一句话解释什么是KV Cache}], temperature: 0.7, max_tokens: 128 }能正常返回内容恭喜你最基础的部署就完成了。但这只是开始真正决定性能的是接下来的参数调优。3.2 单机多卡部署怎么配当模型大到单卡放不下或者你想用多卡提升吞吐时就要用到张量并行Tensor Parallelism。vLLM 通过--tensor-parallel-size参数控制简称 TP。python -m vllm.entrypoints.openai.api_server \ --model /data/models/qwen2.5-32b \ --served-model-name qwen2.5-32b \ --tensor-parallel-size 4 \ --gpu-memory-utilization 0.9 \ --max-model-len 8192 \ --host 0.0.0.0 \ --port 8000--tensor-parallel-size 4表示把模型切分到 4 张卡上。这里有几个硬性约束必须记住TP 数必须能整除模型的注意力头数。比如模型有 32 个注意力头TP 可以是 1、2、4、8、16、32但不能是 3、5、6 这种。设错了启动直接报错。TP 数不能超过可用 GPU 数量。4 张卡最多设 TP4。多卡之间最好有高速互联。NVLink 最好PCIe 次之。如果卡之间只能走 PCIe 且带宽很低TP 的加速效果会打折扣因为每层计算都要跨卡同步。启动多卡服务时vLLM 会先在各卡上加载分片权重这个过程比单卡慢不少32B 模型 4 卡加载大概要几分钟耐心等日志打完。加载完成后显存占用应该是各卡比较均衡的如果发现某张卡特别满、其他卡很空多半是 TP 配置有问题。实操心得多卡部署时用CUDA_VISIBLE_DEVICES0,1,2,3显式指定用哪几张卡避免 vLLM 自动选卡时选到正在被其他任务占用的卡。这个习惯能省掉很多莫名其妙的启动失败。3.3 用 Docker 部署让环境可复现裸机 pip 安装适合调试但生产环境我更推荐 Docker因为环境隔离干净、迁移方便、版本可控。vLLM 官方提供了镜像docker run --runtime nvidia --gpus all \ -v /data/models:/models \ -p 8000:8000 \ --ipchost \ vllm/vllm-openai:latest \ --model /models/qwen2.5-7b \ --served-model-name qwen2.5-7b \ --max-model-len 8192几个关键点解释一下--runtime nvidia --gpus all让容器能访问 GPU。前提是宿主机装好了 NVIDIA Container Toolkit。-v /data/models:/models把宿主机的模型目录挂载进容器避免镜像里重复存一份模型。--ipchost共享宿主机的 IPC 命名空间。这个参数在多卡或高并发场景下很重要不设的话可能因为共享内存不足导致崩溃。镜像 tag 建议锁定具体版本比如vllm/vllm-openai:v0.6.3别用latest否则某天自动更新到新版本可能引入不兼容。Docker 方式的一个小坑是容器内的 CUDA 版本和宿主机驱动版本要匹配。如果启动时报 CUDA driver version is insufficient说明宿主机驱动太老需要升级驱动而不是换镜像。4. 把性能真正压榨出来的调优参数4.1 批处理相关参数怎么调vLLM 的性能上限很大程度上由批处理策略决定。有几个参数直接控制这个--max-num-seqs单个批次里最多同时处理多少个请求默认 256。调大能提升吞吐但会占用更多显存做 KV Cache。显存紧张时调小比如 64 或 128。--max-num-batched-tokens一个批次里最多处理多少个 token默认会根据模型自动推算。这个值越大单批次计算量越大吞吐越高但首 token 延迟也会增加。--enable-chunked-prefill开启分块预填充。长 prompt 的预填充阶段会占用大量计算资源开启这个参数后长 prompt 会被切成小块和 decode 阶段交错执行避免长请求阻塞短请求。这个参数对混合长度请求的场景提升非常明显强烈建议开启。我实测过一个场景一批请求里既有 50 token 的短问题也有 4000 token 的长文档摘要。不开 chunked prefill 时短请求要等长请求的预填充做完才能出结果P99 延迟高得离谱开了之后短请求基本能立刻响应长请求在后台慢慢算整体体验好太多。--enable-chunked-prefill \ --max-num-batched-tokens 8192 \ --max-num-seqs 1284.2 显存与 KV Cache 的精细控制--gpu-memory-utilization是最粗粒度的显存控制但真正决定能扛多少并发的是 KV Cache 的大小。vLLM 启动日志里会打印一行类似GPU KV cache size: 123456 tokens的信息这个数字就是你能同时缓存的 token 总量。如果这个数字太小说明显存被权重占太多留给 KV Cache 的不够。解决办法有两个一是降低--max-model-len二是用量化模型减小权重占用。反过来如果 KV Cache 很大但并发上不去可能是--max-num-seqs设小了请求被排队了。还有一个容易被忽略的参数是--block-size默认 16。它控制 PagedAttention 里每个块存多少 token。调大能减少块管理开销但内部碎片会增加调小则相反。大多数场景保持默认 16 就行除非你在做极致的显存压榨。注意不要盲目追求把--gpu-memory-utilization设到 0.98 甚至 1.0。显存碎片和框架自身的临时分配需要留余量设太高反而容易在运行一段时间后 OOM。0.85 到 0.92 是我用下来比较稳的区间。4.3 量化用精度换显存和速度当显存不够时量化是最直接的出路。vLLM 支持多种量化格式常见的有 AWQ、GPTQ、FP8。它们的取舍关系是这样的量化方式显存节省速度影响精度损失适用场景FP16/BF16基准基准无显存充足追求最高质量FP8约 50%略快极小新卡H100等首选AWQ约 70%较快小消费级卡常用GPTQ约 70%中等小生态成熟兼容性好INT4约 75%快中等显存极度紧张使用量化模型很简单直接加载已经量化好的模型即可vLLM 会自动识别量化配置python -m vllm.entrypoints.openai.api_server \ --model /data/models/qwen2.5-7b-awq \ --quantization awq \ --max-model-len 8192需要提醒的是量化模型的精度损失在通用对话上几乎感知不到但在需要精确推理、代码生成、数学计算的场景下损失可能会被放大。我的经验是7B 以下的小模型尽量别量化本身能力就有限再量化容易变傻32B 以上的大模型量化后依然能打性价比很高。5. 实战中踩过的坑与排查手册5.1 启动阶段最常见的五类报错部署 vLLM 的过程中启动失败占了问题的大头。我把遇到过的报错整理成一张速查表报错关键词根本原因解决办法CUDA out of memory显存不够降 max-model-len、开量化、降 gpu-memory-utilizationCUDA driver version is insufficient驱动太老升级显卡驱动到匹配版本model class not found模型架构不被支持升级 vLLM 版本或换用支持的模型tensor parallel size 不整除TP 数与注意力头数不匹配改成能整除的值Address already in use端口被占用换端口或杀掉占用进程热词里有个具体的报错 valueerror: model class minimaxh3modularpipeline not found这类错误本质上是模型架构太新当前 vLLM 版本还没适配。解决办法只有两个要么升级到最新版 vLLM 碰碰运气要么等官方适配。遇到这种问题别硬刚先去看 vLLM 的 GitHub issue 里有没有人提过通常能找到临时方案或者确认适配进度。5.2 运行中性能不达预期的排查思路服务能起来但速度慢这种问题比启动失败更让人头疼因为它没有明确的报错。我的排查顺序是这样的第一步看 GPU 利用率。用nvidia-smi -l 1持续观察。如果利用率长期低于 50%说明 GPU 在等数据瓶颈可能在 CPU 侧的预处理或者网络传输如果利用率接近 100% 但吞吐还是低说明计算本身到了硬件上限只能靠换卡或量化。第二步看是不是被单请求拖累。如果只有一路请求在跑GPU 利用率低是正常的因为 decode 阶段本来就是显存带宽瓶颈计算单元用不满。这时候要加并发才能看出真实吞吐。第三步检查是不是开了不必要的日志。vLLM 默认的日志级别在高并发下会产生大量 IO拖慢整体性能。生产环境建议把日志级别调到 warning--disable-log-requests这个参数会关闭每个请求的详细日志高并发下能省下可观的 CPU 和 IO 开销。第四步确认没有重复加载模型。我见过有人同时起了多个 vLLM 实例指向同一张卡结果显存互相挤占每个实例都跑得半死不活。一张卡上只跑一个 vLLM 实例要提升吞吐就调参数或加卡别想着靠多实例堆。5.3 几个让我印象深刻的真实案例案例一长上下文导致的间歇性 OOM。有个服务平时跑得好好的但每隔几小时就崩一次。排查后发现是某些请求的输入特别长触发了 KV Cache 的峰值分配把预留的显存余量吃光了。解决办法是把--max-model-len从 32768 降到 16384同时在应用层对超长输入做截断。这个教训是max-model-len 要按实际业务的最长输入来设不要按模型支持的最大值来设。案例二多卡负载不均。4 卡部署一个模型发现第 0 张卡显存占用明显高于其他卡。原因是 vLLM 默认把一些额外的缓冲区放在第 0 张卡上。这属于正常现象但如果差距过大导致第 0 张卡先 OOM可以通过降低--gpu-memory-utilization来缓解。案例三客户端超时误判。有同事反馈服务经常无响应我去看服务端日志一切正常。最后发现是客户端设置的超时时间太短长文本生成还没结束客户端就断了。大模型生成一个几百 token 的回复花十几秒很正常客户端超时要设到 60 秒以上。6. 关于选型与后续扩展的一些个人看法6.1 vLLM、Ollama、SGLang 到底怎么选这三个是热词里被问得最多的组合。我的判断标准很简单看你的核心诉求Ollama个人本地使用、快速验证、模型管理省心。它的优势是开箱即用ollama run一条命令搞定。缺点是并发能力弱不适合做服务端。vLLM生产级推理服务、高并发、需要 OpenAI 兼容 API。它的优势是吞吐高、生态成熟、社区活跃。缺点是对硬件和版本匹配要求高上手门槛比 Ollama 高。SGLang同样面向高并发服务在某些特定场景比如结构化输出、复杂推理链上有独特优化性能有时能超过 vLLM。但生态和文档成熟度目前还不如 vLLM。我的实际选择是开发调试用 Ollama生产部署用 vLLM。两者并不冲突甚至可以共存——Ollama 跑一个小模型做快速验证vLLM 跑主力模型对外服务。热词里vllm ollama被一起搜说明很多人也是这么搭配着用的。6.2 部署之后还能做什么服务跑起来只是第一步。真正让这套系统产生价值的是后面的应用层建设。我目前在做的事情包括在 vLLM 前面加一层网关做鉴权和限流用 Prometheus 采集 vLLM 暴露的指标做监控告警针对特定业务场景用 LoRA 做轻量微调再合并回主模型。热词里lora 微调实战教程 qwen和大模型微调搜索量很高说明大家都在往这个方向走。LoRA 微调后的模型可以直接被 vLLM 加载也可以在 vLLM 里动态加载多个 LoRA 适配器让一个基础模型服务多个业务场景。这个能力对成本控制很有意义——不用为每个场景单独部署一个完整模型。最后分享一个我踩过的小坑vLLM 的版本升级要谨慎。我有一次手贱把生产环境的 vLLM 从 0.6.2 升到 0.6.3结果某个参数的行为变了吞吐直接掉了一半。后来我养成了习惯——升级前先在测试环境跑一遍压测确认性能没有回退再上生产。大模型推理这套东西稳定比新功能重要得多。