1. 先搞清楚这两个东西到底在解决什么问题
很多人第一次接触本地大模型部署,脑子里其实只有一个模糊的念头:我想在自己机器上跑个模型。然后一搜,满屏都是 vLLM 和 Ollama,两边都有人说好,两边都有人劝退。我见过太多人在这两个工具之间反复横跳,装完 Ollama 觉得并发不行,换 vLLM 又发现显存吃紧,最后两头都没跑顺。
问题的根源在于,大多数人把这两个工具当成了同一类东西在做对比,但它们从设计之初瞄准的就是完全不同的场景。Ollama 的核心目标是让个人开发者用一行命令就能把模型跑起来,它把模型下载、量化格式转换、运行时管理、API 暴露这些脏活全包了,你不需要懂 CUDA 版本匹配,不需要手动指定张量并行度,甚至不需要知道什么叫 PagedAttention。而 vLLM 的核心目标是让推理服务在生产环境里扛住高并发,它的看家本领是 PagedAttention 和连续批处理(Continuous Batching),这两个机制决定了它在多请求同时到达时的吞吐量表现远超传统方案。
打个比方,Ollama 像是你家里那台即热式饮水机,拧开就有热水,方便省心,但你没法指望它同时给一百个人供水。vLLM 更像是商用净水系统,安装调试麻烦,管道铺设复杂,但一旦跑起来,整栋楼的用水需求都能扛住。你选哪个,取决于你是自己喝还是给整栋楼供水。
这篇文章会从实际使用场景出发,把两个工具的核心机制、适用边界、部署细节和踩坑经验全部拆开讲清楚。不管你是想在笔记本上跑个模型做实验,还是要给团队搭一套能支撑内部应用的推理服务,看完都能做出适合自己的选择。
2. Ollama 的便利性到底来自哪里
2.1 一行命令背后的封装逻辑
Ollama 最吸引人的地方就是那条ollama run qwen2.5命令。敲下去之后,它自动帮你做了几件事:检测本地是否已有该模型、如果没有就从模型库拉取、根据你的硬件自动选择量化版本、加载到显存并启动推理服务。整个过程你不需要指定任何参数,甚至不需要知道模型文件存在哪里。
这种便利性的代价是灵活性的让渡。Ollama 默认使用 llama.cpp 作为推理后端,llama.cpp 的优势在于对消费级硬件的适配极其广泛,从纯 CPU 到各种消费级显卡都能跑,量化格式也支持得很全(Q4_K_M、Q5_K_M、Q8_0 等)。但 llama.cpp 的批处理能力相对有限,它虽然也支持并发请求,但在高并发场景下的吞吐量表现和 vLLM 不在一个量级。
我实测过在同样一台 4090 机器上,Ollama 跑 Qwen2.5-7B 的 Q4 量化版本,单请求生成速度大概在 60-80 tokens/s,同时来 8 个请求时每个请求的速度会降到 15-20 tokens/s 左右。而 vLLM 跑同样的模型(FP16 精度),单请求速度差不多,但 8 个并发时每个请求还能维持在 40-50 tokens/s。这个差距在并发数继续往上走的时候会拉得更大。
2.2 模型管理的设计哲学
Ollama 的模型管理方式很像 Docker 的镜像管理。每个模型是一个独立的 blob,通过 Modelfile 定义,支持从官方库拉取也支持自己导入 GGUF 文件。这种设计的好处是版本管理清晰,切换模型方便,ollama list一眼就能看到本地有哪些模型。
但这里有个容易被忽略的细节:Ollama 默认把模型存在系统盘的用户目录下(Linux 是/usr/share/ollama/.ollama/models,Windows 是C:\Users\你的用户名\.ollama\models)。一个 7B 的 Q4 模型大概 4-5GB,一个 70B 的 Q4 模型能到 40GB 以上。如果你 C 盘空间紧张,装到一半报磁盘空间不足是常有的事。
解决办法是在启动 Ollama 服务前设置环境变量OLLAMA_MODELS指向其他盘符。Windows 下可以在系统环境变量里加,Linux 下可以在 systemd 的 service 文件里加Environment="OLLAMA_MODELS=/data/ollama/models"。这个操作看起来简单,但很多人是装完才发现空间不够,这时候迁移模型文件还得改配置,不如一开始就规划好。
2.3 什么场景下 Ollama 是最优解
Ollama 真正发光的场景是个人开发、原型验证和小规模内部工具。比如你想给自己的笔记软件加一个本地 AI 助手,或者想做一个离线的文档问答工具,Ollama 的 HTTP API 直接调就行,不需要额外搭服务框架。它的 API 兼容 OpenAI 格式,很多现成的客户端和库可以直接对接。
还有一个容易被忽视的优势是 Ollama 对硬件的宽容度。它能在没有独立显卡的机器上跑,虽然速度慢,但至少能跑。对于预算有限或者只是想先试试水的用户来说,这个门槛低到几乎没有。我见过有人用一台老旧的 ThinkPad 跑 3B 模型做文本分类,虽然每秒只能生成几个 token,但对于批处理任务来说完全够用。
3. vLLM 的并发能力是怎么实现的
3.1 PagedAttention 解决了什么核心问题
要理解 vLLM 为什么快,得先理解 Transformer 推理时显存是怎么被消耗的。在生成每个 token 的时候,模型需要缓存之前所有 token 的 Key 和 Value 矩阵,这就是所谓的 KV Cache。传统方案会为每个请求预分配一块连续的显存来存 KV Cache,按最大可能长度来分配。问题是大多数请求的实际生成长度远小于最大长度,预分配的空间大量浪费,而且显存碎片化严重,导致能同时处理的请求数很有限。
PagedAttention 的思路借鉴了操作系统的虚拟内存分页机制。它把 KV Cache 切成固定大小的块(block),每个块可以存在显存的任意位置,通过一个块表来维护逻辑上的连续性。这样一来,显存利用率能从传统的 20-40% 提升到 90% 以上,同样一块显卡能同时处理的请求数直接翻倍甚至更多。
这个机制带来的实际效果是:在 4090 上跑 Qwen2.5-7B,vLLM 可以同时处理 30-50 个并发请求而不会 OOM,而传统方案可能到 10 个请求就开始排队了。对于需要支撑多人同时使用的场景,这个差距是决定性的。
3.2 连续批处理如何提升吞吐量
连续批处理(Continuous Batching)是 vLLM 的另一个核心机制。传统的静态批处理是这样的:攒一批请求,一起送进模型,等这批全部生成完了再处理下一批。问题是同一批里有的请求可能只生成 10 个 token 就结束了,有的要生成 500 个,短的必须等长的,GPU 利用率在后期会大幅下降。
连续批处理的做法是:每个推理步(step)都重新组批,已经生成完的请求立刻退出,新的请求随时可以加入。这样 GPU 几乎不会空转,吞吐量能提升 2-4 倍。这个机制在请求长度差异大的场景下效果尤其明显,比如同时有短问答和长文生成的任务混合在一起。
我做过一个对比测试:用同样的模型和硬件,模拟 50 个请求同时到达,其中一半是短请求(生成 50 token 以内),一半是长请求(生成 500 token 以上)。静态批处理的总完成时间是连续批处理的 2.8 倍。这个差距在真实业务场景里直接反映为用户的等待时间和服务器的成本。
3.3 张量并行与多卡扩展
当单个显卡装不下模型或者需要更高吞吐量时,vLLM 支持张量并行(Tensor Parallelism),把模型切分到多张显卡上。比如 70B 的模型用 4 张 A100 做张量并行,每张卡负责模型的一部分层,推理时通过 NCCL 做卡间通信。
这里有个实操经验:张量并行的卡数最好是 2 的幂次,而且卡之间的互联带宽越高越好。如果是 PCIe 互联而不是 NVLink,通信开销会明显增加,扩展效率可能只有 60-70%。我见过有人用 4 张 3090 通过 PCIe 做张量并行跑 70B 模型,实际吞吐量只比单卡 4090 跑 7B 模型高一点,投入产出比很低。所以多卡方案要算清楚账,不是卡多就一定划算。
4. 部署实操中的关键差异与踩坑记录
4.1 安装过程的环境依赖对比
Ollama 的安装基本是零依赖的。Windows 下下载一个 exe 双击安装,Linux 下一条 curl 脚本搞定,macOS 直接 brew install。它自带 CUDA 运行时,不需要你系统里预装 CUDA Toolkit。这一点对新手极其友好,我见过太多人卡在 CUDA 版本不匹配上,Ollama 直接绕过了这个问题。
vLLM 的安装就没这么省心了。它是 Python 包,通过 pip 安装,但依赖链很长:需要正确版本的 PyTorch、CUDA Toolkit、NCCL、FlashAttention 等。最常遇到的问题就是 pip 自动解析依赖时把已经装好的 PyTorch 版本给换了,导致其他依赖 PyTorch 的项目跑不起来。我的建议是永远在虚拟环境里装 vLLM,而且装之前先pip freeze > requirements_backup.txt备份当前环境。
另一个常见坑是 vLLM 对 CUDA 版本有要求。比如某个版本的 vLLM 可能只支持 CUDA 12.1-12.4,你系统里是 11.8 就装不上。这时候要么升级 CUDA,要么找对应旧版本的 vLLM。我一般会先查 vLLM 官方文档的兼容性表格,确认版本匹配再动手。
4.2 模型加载与显存占用的实际表现
Ollama 加载模型时会根据你的显存自动选择是否 offload 到 GPU,以及 offload 多少层。这个自动决策大多数时候是合理的,但偶尔会出现显存明明够却只 offload 了一部分的情况。这时候可以通过ollama run时的--num-gpu参数手动指定,或者在 Modelfile 里设置PARAMETER num_gpu 99强制全部加载到 GPU。
vLLM 加载模型时需要你显式指定--gpu-memory-utilization参数,默认是 0.9,意思是使用 90% 的显存。这个参数很关键:设太高容易 OOM,设太低浪费显存。我的经验是 7B 模型设 0.85-0.9 比较稳,70B 模型如果做张量并行,每张卡设 0.9 左右。另外--max-model-len也要根据实际需求设,设得越大 KV Cache 占用越多,能同时处理的请求数就越少。如果业务场景里大多数请求不超过 4096 token,就没必要设成 32768。
4.3 API 服务化的不同路径
Ollama 启动后默认在 11434 端口提供 HTTP API,兼容 OpenAI 的/v1/chat/completions接口。你不需要额外写任何代码,直接就能用。对于快速验证和轻量集成来说,这个设计非常省事。
vLLM 也提供 OpenAI 兼容的 API 服务,通过vllm serve命令启动。但它的配置项多得多,需要指定模型路径、端口、张量并行度、显存利用率等参数。好处是你可以精细控制服务的每一个方面,比如设置--max-num-seqs控制最大并发序列数,设置--swap-space控制 CPU 交换空间大小。这些参数在调优时非常有用,但也意味着更高的学习成本。
我一般会写一个启动脚本把常用参数固化下来,比如:
python -m vllm.entrypoints.openai.api_server \ --model /data/models/Qwen2.5-7B-Instruct \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.88 \ --max-model-len 8192 \ --max-num-seqs 64 \ --port 8000这样每次启动不用重新想参数,也方便版本管理。
5. 并发场景下的实测数据与选型决策
5.1 不同并发数下的吞吐量对比
我在一台 4090(24GB 显存)的机器上做了组对比测试,模型用 Qwen2.5-7B,Ollama 用 Q4_K_M 量化版本,vLLM 用 FP16 精度。测试方法是模拟不同数量的并发请求,每个请求要求生成 256 个 token,记录总完成时间和平均每请求延迟。
| 并发数 | Ollama 总耗时 | vLLM 总耗时 | Ollama 平均延迟 | vLLM 平均延迟 |
|---|---|---|---|---|
| 1 | 4.2s | 3.8s | 4.2s | 3.8s |
| 4 | 9.8s | 5.1s | 9.8s | 5.1s |
| 8 | 21.5s | 7.3s | 21.5s | 7.3s |
| 16 | 52.3s | 11.6s | 52.3s | 11.6s |
| 32 | 超时(>120s) | 19.8s | - | 19.8s |
数据很直观:单请求时两者差距不大,vLLM 略快因为 FP16 精度更高。但并发数一上去,差距迅速拉开。到 16 并发时 vLLM 的总耗时只有 Ollama 的 22%,32 并发时 Ollama 已经基本不可用了。
这个测试结果不是说 Ollama 不好,而是说明它的设计目标本来就不是高并发。如果你只是自己用或者给两三个人用,Ollama 完全够。但如果要支撑一个团队或者对外提供服务,vLLM 是更合理的选择。
5.2 显存占用与模型精度的权衡
Ollama 用 Q4 量化能在 24GB 显存上跑 7B 模型还有富余,甚至能跑 14B 的 Q4 模型。vLLM 跑 FP16 的 7B 模型大概占 14-16GB 显存(包括 KV Cache),跑 14B 的 FP16 就需要 28GB 以上,单张 4090 装不下。
但 vLLM 也支持量化,可以用 AWQ 或 GPTQ 格式的量化模型。不过量化后的模型在 vLLM 上的推理速度优势会缩小,因为量化解码本身有开销。我的经验是:如果显存够,vLLM 跑 FP16 是吞吐量最优解;如果显存紧张,用 AWQ 量化在 vLLM 上跑也比 Ollama 的 Q4 快,但差距没有 FP16 那么大。
这里有个容易踩的坑:不是所有量化格式 vLLM 都支持。GGUF 格式 vLLM 支持得不好,最好用 AWQ 或 GPTQ。而 Ollama 主要用 GGUF,两者模型文件不通用。所以如果你先用了 Ollama 攒了一堆 GGUF 模型,转 vLLM 的时候需要重新下载或转换模型格式,这个迁移成本要提前考虑。
5.3 什么情况下该从 Ollama 迁移到 vLLM
判断标准其实很简单:当你发现请求开始排队、用户抱怨响应变慢、GPU 利用率上不去的时候,就是该考虑 vLLM 的信号了。具体来说,如果同时在线用户超过 5-10 个,或者你的应用需要处理突发流量,Ollama 就会成为瓶颈。
另一个信号是当你需要更精细的控制时。比如你想限制单个请求的最大 token 数来防止滥用,想动态调整批处理大小来平衡延迟和吞吐,想监控每个请求的 GPU 占用情况,这些在 vLLM 里都有对应的参数和指标,在 Ollama 里就比较难做到。
但迁移不是没有成本的。除了前面说的模型格式问题,还有运维复杂度的提升。vLLM 服务挂了不会自动重启,需要你配 systemd 或者用容器编排工具来管理。Ollama 作为系统服务安装后基本不用管,vLLM 则需要你盯着日志、调参数、处理 OOM。所以如果并发需求不明显,留在 Ollama 是更省心的选择。
6. 生产环境部署的进阶考量
6.1 容器化部署的注意事项
生产环境我强烈建议用 Docker 部署 vLLM,而不是直接在宿主机上 pip install。原因有几个:环境隔离干净,不会污染宿主机的 Python 环境;版本管理方便,换个镜像 tag 就能切换 vLLM 版本;资源限制好做,可以用--gpus指定用哪些卡,用--memory限制内存。
但容器化有个坑要注意:vLLM 容器需要访问 GPU,必须装 nvidia-container-toolkit,而且容器内的 CUDA 版本要和宿主机的驱动兼容。我遇到过宿主机驱动太旧,新版本 vLLM 镜像跑不起来的情况,最后是升级了驱动才解决。所以部署前先nvidia-smi看一下驱动版本,对照 vLLM 文档确认兼容性。
另外模型文件最好挂载进容器而不是打包进镜像,否则镜像体积会大到离谱。用-v /data/models:/models把模型目录挂进去,启动时指定/models/Qwen2.5-7B-Instruct就行。
6.2 监控与自动恢复
vLLM 服务在生产环境跑,必须配监控。最基础的监控指标包括:GPU 利用率、显存占用、请求队列长度、每秒生成 token 数、请求延迟分布。这些指标 vLLM 通过 Prometheus 格式暴露在/metrics端点,用 Prometheus 抓取后配合 Grafana 展示就行。
自动恢复方面,我一般用 systemd 的Restart=always配合健康检查。但要注意 vLLM 启动加载模型需要时间,7B 模型大概 30-60 秒,70B 模型可能几分钟。如果健康检查间隔设太短,服务还没加载完就被判定为不健康然后重启,会陷入无限重启循环。我的做法是健康检查的initialDelaySeconds设成 120 秒以上,给模型加载留足时间。
还有一个经验是给 vLLM 进程设显存清理的钩子。有时候服务异常退出后显存没有完全释放,直接重启会 OOM。可以在启动脚本里加一段nvidia-smi --gpu-reset或者等几秒让驱动回收显存。这个细节看起来小,但在自动化运维里能省很多事。
6.3 请求队列与限流策略
vLLM 内部有请求队列,当并发数超过--max-num-seqs时,新请求会排队等待。这个队列长度是有限的,满了之后新请求会被拒绝。所以在 vLLM 前面最好加一层网关做限流,比如用 Nginx 的limit_req模块或者自己写个简单的令牌桶。
限流策略要根据你的业务场景来定。如果是内部工具,可以宽松一点,排队就排队,用户能接受等待。如果是对外服务,就要设超时和拒绝策略,避免请求堆积导致雪崩。我一般会在网关层设一个总超时(比如 60 秒),超过就返回 503,同时给用户一个友好的提示。
另外建议在 vLLM 启动参数里设--disable-log-requests,否则每个请求的详细日志会刷屏,在高并发下日志 IO 本身就会成为瓶颈。需要调试的时候再临时打开。
7. 一些容易被忽略的细节和我的个人建议
Ollama 和 vLLM 并不是非此即彼的关系,很多团队实际上是两个都用。开发阶段用 Ollama 快速验证想法,模型选型和 prompt 调优都在 Ollama 上做,因为改起来快。等确定要上生产了,再把模型和配置迁移到 vLLM。这样既享受了 Ollama 的便利,又拿到了 vLLM 的性能。
迁移的时候有个小技巧:Ollama 的 Modelfile 里定义的 system prompt 和参数(temperature、top_p 等),在 vLLM 里需要通过 API 请求的 body 传进去,或者用--served-model-name配合客户端的默认配置。不要指望两边行为完全一致,迁移后一定要做一轮回归测试,对比输出质量有没有变化。
还有一个关于模型选择的建议:不是所有模型在 vLLM 上的表现都一样。有些模型对 PagedAttention 的适配更好,有些模型因为注意力机制的特殊实现(比如滑动窗口注意力)在 vLLM 上需要额外配置。选模型的时候除了看效果,也要看 vLLM 官方文档里有没有标注支持。我一般优先选 vLLM 官方示例里出现过的模型,踩坑概率小很多。
最后说一个硬件层面的经验:vLLM 对显存带宽比 Ollama 更敏感。同样是 4090,如果显存被其他进程占用了一部分,vLLM 的性能下降比 Ollama 更明显。所以跑 vLLM 的机器最好专卡专用,不要同时跑其他吃显存的任务。如果实在要共享,用 MIG(Multi-Instance GPU)把显卡切分比共享整卡更稳定,但 MIG 只在 A100 以上的卡支持,消费级显卡没有这个功能。
这些就是我在实际部署和使用这两个工具过程中积累下来的经验。选哪个工具,最终还是要回到你的具体场景:几个人用、什么硬件、能不能接受运维成本、对延迟和吞吐的要求是什么。把这些想清楚了,答案自然就出来了。