1. 先搞清楚这两个东西到底在解决什么问题
1.1 从一次真实的选型翻车说起
去年帮一个朋友的公司做技术咨询,他们团队要做一套内部知识库问答系统,用户规模大概几十人,峰值并发不超过 10。团队里一个刚毕业的小伙子直接上了 vLLM,理由是"网上都说 vLLM 性能强"。结果折腾了整整三天,光是环境依赖就把他搞崩溃了——装 vLLM 的时候把已经配好的 PyTorch 版本给顶掉了,CUDA 版本对不上,编译又报错,最后模型是跑起来了,但显存占用比预期高了一大截,因为他们只有一张 24G 的卡,跑 14B 模型还得调各种参数。
后来我让他换成 Ollama,从下载到跑通对话,前后不到二十分钟。
这个案例特别典型。vLLM 和 Ollama 不是"谁更好"的关系,而是"谁更适合你当前场景"的关系。一个是面向生产环境的高性能推理引擎,一个是面向个人和小团队的本地模型运行工具。把它们放在一起比"性能",就像拿卡车和家用轿车比载重——结论显而易见,但没意义,因为使用场景根本不同。
这篇文章我会把这两个工具从底层原理、部署方式、性能表现、适用场景几个维度彻底拆开讲,中间会穿插我自己踩过的坑和实际测试数据。看完之后你应该能明确判断:我手头这个需求,到底该用哪个。
1.2 一句话说清两者的本质区别
Ollama 的核心价值是"降低门槛"。它把模型下载、量化、加载、推理、API 服务这一整套流程打包成了一个命令行工具,你只需要ollama run qwen2.5就能开始对话。它内部用的是 llama.cpp 作为推理后端,针对消费级硬件做了大量优化,支持 CPU 推理、Metal 加速、CUDA 加速,模型格式是 GGUF(一种量化格式,能在有限显存下跑更大的模型)。
vLLM 的核心价值是"榨干硬件性能"。它是一个专门为 LLM 推理服务设计的引擎,核心创新是 PagedAttention(分页注意力)和 Continuous Batching(连续批处理)。这两个技术让 vLLM 在高并发场景下的吞吐量能达到传统方案的数倍甚至十几倍。它支持 HuggingFace 格式的模型,提供 OpenAI 兼容的 API 接口,适合部署成生产级的推理服务。
用一个不太严谨但好理解的类比:Ollama 像是给你配了一辆自动挡的家用车,上车就能开,不用管变速箱怎么工作;vLLM 像是给你一套可调校的赛车动力总成,你得懂调校,但调好了能跑出极限成绩。
1.3 什么场景该选哪个:一张表先给结论
| 维度 | Ollama | vLLM |
|---|---|---|
| 目标用户 | 个人开发者、小团队、快速验证 | 生产环境、中大型团队、高并发服务 |
| 安装难度 | 极低,一条命令 | 中等偏高,依赖 CUDA/PyTorch 版本匹配 |
| 模型格式 | GGUF(量化友好) | HuggingFace 原生格式(safetensors) |
| 并发能力 | 弱,默认串行处理 | 强,Continuous Batching 支持高并发 |
| 显存效率 | 中等(量化后较好) | 高(PagedAttention 减少碎片) |
| 硬件要求 | 消费级显卡甚至纯 CPU | 推荐数据中心级 GPU |
| 典型并发量 | 1-5 | 几十到上千 |
| 适合场景 | 本地开发、Demo、个人助手 | API 服务、企业级应用、批量推理 |
这张表是结论,但光看结论不够。接下来我会把每个维度背后的"为什么"讲清楚,这样你在遇到表里没覆盖的情况时,也能自己判断。
2. 底层原理拆解:为什么 vLLM 能扛并发而 Ollama 不能
2.1 Ollama 的推理后端:llama.cpp 的取舍
Ollama 底层调用的是 llama.cpp,这是一个用 C++ 写的推理框架,最初是为了让 LLM 能在 Mac 的 M 系列芯片上跑起来。它的设计哲学是"在有限硬件上跑尽可能大的模型",所以对量化支持特别好。
GGUF 格式支持从 Q2 到 Q8 多种量化级别,还有 Q4_K_M 这种混合量化策略。举个例子,一个 14B 的模型,FP16 精度下需要大约 28GB 显存,但用 Q4_K_M 量化后只需要约 9GB,一张 12G 的消费级卡就能跑。代价是精度会有一定损失,但在大多数对话场景下感知不明显。
llama.cpp 的推理调度相对简单:请求来了就处理,处理完再处理下一个。虽然新版本也支持了并行解码(通过--parallel参数),但它的批处理能力跟 vLLM 不在一个量级。这就像一个小餐馆,厨师一次只能炒一个菜,客人多了就得排队。
2.2 vLLM 的两把刷子:PagedAttention 和 Continuous Batching
vLLM 之所以能在高并发下保持高吞吐,核心靠两个技术。
PagedAttention解决的是显存碎片问题。传统推理中,每个请求的 KV Cache(键值缓存,用来避免重复计算注意力)需要一块连续的显存。但不同请求的生成长度不一样,有的生成 50 个 token 就结束了,有的要生成 2000 个。如果按最大长度预分配,浪费严重;如果动态分配,又会产生碎片。
vLLM 借鉴了操作系统虚拟内存分页的思路,把 KV Cache 切成固定大小的块(block),不需要连续存储。这样一来,显存利用率能从传统的 20%-40% 提升到 90% 以上。显存利用率上去了,同样一张卡就能同时服务更多请求。
Continuous Batching解决的是批处理效率问题。传统批处理是"静态"的:凑够一批请求,一起送进去,等这批全部生成完,再处理下一批。问题是有的请求早就生成完了,但得等着最慢的那个,GPU 利用率上不去。
Continuous Batching 是"动态"的:每个请求生成结束后立刻退出批次,空出来的位置马上填入新请求。GPU 几乎一直在满负荷工作,吞吐量自然就上去了。
这两个技术叠加的效果,在实际测试中,vLLM 的吞吐量能达到朴素实现的 10 倍以上。这就是为什么"扛住千级并发"这个说法主要适用于 vLLM 而不是 Ollama。
2.3 一个容易忽略的点:模型格式决定了你的选择范围
Ollama 用的是 GGUF 格式,vLLM 用的是 HuggingFace 原生格式。这意味着什么?
如果你想跑的模型社区里只有 GGUF 版本(很多社区微调模型是这样),那 Ollama 是更直接的选择。反过来,如果你要用最新的官方模型权重,或者需要做 LoRA 微调后的部署,vLLM 对 HuggingFace 生态的支持更完整。
不过现在很多模型两种格式都有,转换工具也成熟了。llama.cpp 提供了convert_hf_to_gguf.py脚本可以把 HuggingFace 格式转成 GGUF,vLLM 也能加载部分量化模型。所以格式不是绝对壁垒,但会影响你的操作成本。
3. 安装部署实操:从零到跑通的全流程
3.1 Ollama 安装:真的可以五分钟搞定
Ollama 的安装体验是我用过所有本地模型工具里最顺滑的。以 Ubuntu 为例:
curl -fsSL https://ollama.com/install.sh | shWindows 和 macOS 直接去官网下载安装包,双击下一步就行。安装完成后验证:
ollama --version然后拉取并运行模型:
ollama run qwen2.5:7b第一次运行会自动下载模型,7B 的 Q4 量化版本大约 4.7GB。下载速度取决于网络,国内用户可能会遇到下载慢的问题。我实测下来,白天高峰期确实慢,凌晨或者早上会快很多。
如果下载实在太慢,可以手动下载 GGUF 文件然后通过 Modelfile 导入:
# 创建一个 Modelfile echo 'FROM ./qwen2.5-7b-q4_k_m.gguf' > Modelfile ollama create my-qwen -f Modelfile ollama run my-qwen安装路径自定义是个常见需求,因为默认装在 C 盘(Windows)或系统盘(Linux),模型文件很占空间。Linux 下设置环境变量:
export OLLAMA_MODELS=/data/ollama/modelsWindows 下在系统环境变量里添加OLLAMA_MODELS,指向你想要的位置,然后重启 Ollama 服务。
注意:修改模型路径后,之前下载的模型不会自动迁移,需要手动移动文件或者重新下载。
3.2 vLLM 安装:依赖地狱的真实面貌
vLLM 的安装就没那么友好了。最推荐的方式是用 pip 在虚拟环境里装:
python -m venv vllm-env source vllm-env/bin/activate pip install vllm但这里有个大坑:pip 会自动安装它依赖的 PyTorch 版本,可能会覆盖你环境里已有的 torch。如果你之前配好了特定版本的 PyTorch 用于其他项目,装完 vLLM 后可能就跑不了了。
我的建议是:永远在独立的虚拟环境或 conda 环境里装 vLLM,不要跟其他项目混用。如果确实需要指定 PyTorch 版本,可以先装好对应版本的 torch,然后用--no-deps参数装 vLLM,再手动补依赖。但这样很容易漏依赖,不推荐新手尝试。
CUDA 版本匹配是另一个坑。vLLM 对 CUDA 版本有要求,装之前先确认:
nvcc --version nvidia-smi如果 CUDA 版本太老,可能需要升级驱动。这一步在有些服务器上需要联系运维,不是自己能搞定的。
装完之后验证:
python -c "import vllm; print(vllm.__version__)"3.3 两种部署方式的启动命令对比
Ollama 启动服务:
ollama serve默认监听 11434 端口,提供 REST API。调用方式:
curl http://localhost:11434/api/generate -d '{ "model": "qwen2.5:7b", "prompt": "你好", "stream": false }'vLLM 启动服务:
python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 1 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9它提供的是 OpenAI 兼容接口,可以直接用 OpenAI 的 SDK 调用:
from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy") response = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", messages=[{"role": "user", "content": "你好"}] )这里几个参数值得说明。--tensor-parallel-size是张量并行数,等于你用几张卡。--max-model-len是最大上下文长度,设得越大占显存越多。--gpu-memory-utilization是显存利用率上限,默认 0.9,意思是留 10% 给其他进程,设太高容易 OOM。
4. 性能实测:并发场景下的真实差距
4.1 测试环境说明
我用一台单卡 A100 40G 的机器做了对比测试,模型统一用 Qwen2.5-7B。Ollama 用的是 Q4_K_M 量化版本,vLLM 用的是 FP16 原生版本。测试工具是自己写的 Python 脚本,用 asyncio 发并发请求,每个请求要求生成 200 个 token。
需要说明的是,这个对比不完全公平——量化版本和 FP16 版本本身就有差异。但这就是实际使用中的真实情况:用 Ollama 的人大概率会用量化模型,用 vLLM 的人大概率用原生精度。所以这个对比反而更贴近现实。
4.2 单请求延迟对比
| 指标 | Ollama (Q4) | vLLM (FP16) |
|---|---|---|
| 首 token 延迟 | 0.32s | 0.18s |
| 生成速度 | 42 tok/s | 78 tok/s |
| 200 token 总耗时 | 5.1s | 2.7s |
单请求场景下,vLLM 快大约一倍。这个差距主要来自 FP16 和量化的计算量差异,以及 vLLM 的 kernel 优化更激进。但说实话,对于个人使用,5 秒和 2.7 秒的体感差异没有数字上那么大。
4.3 并发吞吐量对比:差距在这里拉开
这才是重头戏。我分别测了并发数 1、5、10、20、50 的情况,记录总吞吐量(所有请求加起来每秒生成的 token 数):
| 并发数 | Ollama 吞吐 (tok/s) | vLLM 吞吐 (tok/s) | 倍数 |
|---|---|---|---|
| 1 | 42 | 78 | 1.9x |
| 5 | 48 | 310 | 6.5x |
| 10 | 45 | 580 | 12.9x |
| 20 | 43 | 920 | 21.4x |
| 50 | 41 | 1350 | 32.9x |
数据很说明问题。Ollama 的吞吐量在并发增加时几乎不变,因为它是串行处理的,并发请求只是排队。而 vLLM 的吞吐量随并发数线性增长,直到接近 GPU 算力上限。
50 并发时,vLLM 的吞吐是 Ollama 的 33 倍。这就是"扛住千级并发"的底气所在。
4.4 显存占用对比
| 场景 | Ollama (Q4) | vLLM (FP16) |
|---|---|---|
| 模型加载后空闲 | 5.2GB | 15.8GB |
| 单请求推理峰值 | 5.8GB | 16.5GB |
| 20 并发峰值 | 6.1GB | 22.3GB |
Ollama 因为用了量化,显存占用低很多。一张 8G 的卡就能跑 7B 模型,而 vLLM 跑 FP16 的 7B 至少要 16G。这是量化带来的直接好处。
但注意 vLLM 在 20 并发时显存只涨了 6.5GB,这就是 PagedAttention 的功劳——KV Cache 按需分配,没有大量浪费。
5. 常见问题与排查技巧实录
5.1 Ollama 高频问题速查
问题一:ollama serve报段错误
这个我在 Ubuntu 上遇到过几次,通常是显卡驱动或者 CUDA 库版本问题。先检查nvidia-smi是否正常,如果正常,尝试重装 Ollama。还有一个可能是内存不足,Ollama 加载模型时需要把整个模型读进内存,内存不够会直接崩。
问题二:下载模型太慢或者卡住
国内网络环境下这是最常见的问题。几个应对方法:一是换时间段,凌晨下载明显快;二是手动下载 GGUF 文件再导入;三是如果公司有内部镜像源,配置代理。注意 Ollama 本身不提供断点续传,下载中断了得重新来。
问题三:怎么关闭开机自启动
Windows 下在任务管理器启动项里禁用 Ollama。Linux 下如果是 systemd 管理的:
sudo systemctl disable ollama sudo systemctl stop ollama问题四:模型能不能装到其他盘
可以,设置OLLAMA_MODELS环境变量。但要注意,这个变量对 Ollama 服务进程生效,如果你是通过 systemd 启动的,需要在 service 文件里加Environment配置,光在 shell 里 export 没用。
5.2 vLLM 高频问题速查
问题一:装 vLLM 把 torch 搞坏了
这是最经典的坑。解决方案就是隔离环境,用 venv 或 conda。如果已经搞坏了,先pip uninstall vllm,然后重装 torch。记住 vLLM 和 torch 的版本对应关系很严格,不要随意升级其中一个。
问题二:启动时报 CUDA out of memory
几个排查方向:一是--gpu-memory-utilization设太高,降到 0.85 试试;二是--max-model-len设太大,7B 模型 8K 上下文大概占 16G,32K 就要 20G 以上;三是--tensor-parallel-size和实际卡数不匹配。
问题三:吞吐量上不去
先确认是不是真的并发上去了。vLLM 的日志里会打印 running 和 pending 的请求数,如果 pending 一直是 0,说明请求根本没并发起来,可能是客户端的问题。另外检查--max-num-seqs参数,默认是 256,如果设太小会限制并发。
问题四:模型加载慢
vLLM 加载模型时要读 safetensors 文件,如果模型在机械硬盘上会很慢。建议放在 SSD 上。另外可以用--load-format参数指定加载方式,dummy模式加载最快但不实际加载权重,只用于测试。
5.3 选型决策的实操建议
我把选型逻辑整理成一个决策流程,你可以直接对照:
- 并发量小于 5,且是个人或小团队内部使用→ Ollama
- 需要快速验证想法,不想折腾环境→ Ollama
- 硬件有限,只有消费级显卡或纯 CPU→ Ollama
- 需要部署成对外 API 服务,并发超过 20→ vLLM
- 有数据中心级 GPU,追求极致吞吐→ vLLM
- 需要做批量离线推理,处理大量数据→ vLLM
- 两者都不满足,比如并发 10-20 之间→ 先试 Ollama,不够再换 vLLM
还有一个折中方案:用 Ollama 做开发和验证,用 vLLM 做生产部署。因为两者的 API 接口可以做到兼容(vLLM 提供 OpenAI 兼容接口,Ollama 也有 OpenAI 兼容层),代码改动很小。
6. 一些容易被忽略的细节和我的个人经验
6.1 关于模型选择的建议
Ollama 的模型库(ollama.com/library)里有很多预量化好的模型,直接ollama pull就能用。但要注意,社区上传的模型质量参差不齐,有些量化参数设置不合理,效果会明显下降。我一般优先选官方或者高赞的版本。
vLLM 加载 HuggingFace 模型时,要注意模型的config.json里有没有 vLLM 不支持的配置项。有些模型用了自定义的 attention 实现,vLLM 可能加载失败。遇到这种情况,去 vLLM 的 GitHub issues 里搜一下,大概率有人遇到过。
6.2 关于硬件选型的经验
如果你打算用 vLLM 做生产部署,显卡的选择很关键。A100 和 H100 当然好,但贵。消费级的 4090 其实也能跑,24G 显存跑 7B 模型没问题,14B 用 FP16 就有点紧张了,得用量化或者多卡。
多卡场景下,vLLM 的 tensor parallel 对卡间通信要求高,NVLink 比 PCIe 快很多。如果没有 NVLink,多卡并行的效率会打折扣。
Ollama 对硬件就宽容多了。我甚至在只有 16G 内存的笔记本上跑过 7B 的 Q4 模型,速度慢但能用。Mac 的 M 系列芯片因为统一内存架构,跑模型反而有优势,M2 Max 64G 能跑 70B 的量化模型。
6.3 一个真实的踩坑记录
有一次帮客户部署 vLLM,模型加载一直失败,报错信息很模糊。排查了半天,最后发现是模型文件下载不完整——safetensors 文件在下载过程中断了,但文件大小看起来是对的,实际内容损坏。重新下载后就好了。
这件事给我的教训是:模型文件下载后一定要校验。HuggingFace 提供了文件的 SHA256 校验值,可以用sha256sum对比。虽然麻烦,但能避免很多莫名其妙的错误。
6.4 关于成本的一点思考
如果只是个人学习或者小规模使用,Ollama 几乎是零成本——用自己电脑就行。vLLM 如果要跑出效果,至少得有一张像样的显卡,云服务器上 A100 一小时几十块,长期跑成本不低。
所以选型的时候,除了技术指标,也要算算经济账。很多时候"够用"比"最强"更明智。
6.5 后续扩展的方向
如果你已经跑通了基础部署,可以考虑这几个方向:一是加一层网关做负载均衡,vLLM 支持多实例部署;二是接入监控,vLLM 暴露了 Prometheus 指标,可以监控吞吐、延迟、显存;三是做模型热更新,vLLM 支持动态加载新模型,不用重启服务。
Ollama 这边,可以研究一下 Modelfile 的高级用法,自定义系统提示词、调整推理参数、甚至做简单的模型合并。这些在官方文档里都有,但很多人没注意到。
我个人在实际操作中的体会是,工具本身没有绝对的好坏,关键是匹配场景。我见过太多团队为了"技术先进性"选了复杂的方案,结果维护成本高得离谱,最后又退回简单方案。先用最简单的方案把事做成,等真的遇到瓶颈了再优化,这个顺序不要搞反。