直接结论

Ollama、vLLM 与 llama.cpp 的能力有交集,但优化目标不同。 Ollama 适合低摩擦的本地模型管理与开发工作流,vLLM 适合由调度器驱动的 GPU 服务和分布式扩展,llama.cpp 适合 GGUF 可移植部署与底层运行时控制。不存在脱离工作负载的统一冠军:满足模型质量、延迟、吞吐、硬件、安全与 API 契约的最小运维栈,才是合理选型。

本文只回答工作负载选型与评测。如果需要 Modelfile、原生 API、结构化输出和模型驻留细节,请阅读 Ollama 本地部署指南,避免两篇文章争夺同一搜索意图。

真正需要比较的六层契约

本地大模型服务是一条契约链,而不是一个推理二进制。没有固定整条链时,所谓框架对比往往实际比较了不同模型、模板或量化器。

flowchart LR A["模型制品与 Tokenizer"] --> B["运行时与计算 Kernel"] B --> C["调度器与 KV Cache"] C --> D["HTTP 与 API 契约"] D --> E["网关与安全边界"] E --> F["工作负载 SLO 与质量"]

六层边界分别是:

  1. 模型契约:权重修订、Tokenizer、Chat Template、Adapter、量化和上下文策略。
  2. 执行运行时:CPU/GPU 后端、Kernel、内存放置和设备拓扑。
  3. 服务调度器:排队、批处理、准入、抢占和 KV Cache 分配。
  4. 协议表面:原生接口、兼容接口、流式响应、usage、取消和错误语义。
  5. 运维边界:鉴权、TLS、限流、租户隔离、可观测与回滚。
  6. 负载契约:输入输出长度分布、到达模式、质量目标和服务等级目标。

这个拆分可以避免两类常见错误:把 GGUF 与更高精度的 Hugging Face 权重当成同一个模型,以及用核心 Token 生成速度代替端到端服务容量。

Ollama、vLLM 与 llama.cpp 对比

三者的关键差异是运维意图,而不是某个固定并发人数。

决策维度 Ollama vLLM llama.cpp / llama-server
主要定位 本地开发与小型自托管服务的集成工作流 面向吞吐的 GPU API 与分布式服务 可移植 GGUF 运行时、边缘/CPU 和底层控制
模型工作流 Ollama 模型库与 Modelfile 生命周期 常见为 Hugging Face 风格模型与 Tokenizer 仓库 GGUF 文件与 llama.cpp 转换工具链
并发服务 内存允许时并行请求,并由有界队列承接等待 调度器驱动的批处理与显式服务控制 llama-server 并行 slot 与连续批处理
内存模型 上下文、并行度、驻留模型和缓存类型共同决定容量 分页 KV Cache、调度上限和并行拓扑共同决定容量 上下文、slot、batch、缓存类型和卸载共同决定容量
硬件范围 通过封装工作流支持 CPU、部分 GPU 与 Apple Silicon 以加速器服务为核心,具体平台以当前官方文档为准 广泛 CPU/GPU 后端和设备相关构建
扩展方式 多模型驻留及可用 GPU 放置,需观察实际分配 张量并行、流水线并行与多节点部署 在支持的后端使用 layer、row 或 tensor split
兼容接口 部分 OpenAI API 与 Ollama 原生 API 多种 OpenAI 兼容服务接口 OpenAI 兼容路由及其他已文档化路由
最强选型理由 本地工作流阻力最低 服务调度与生产指标更完整 可移植性与运行时控制最强
主要风险 把开发友好型本地服务直接暴露到生产网络 未定义 SLO 就过早调优复杂 GPU 服务 自行承担构建、模型、服务和平台细节

Ollama 并非只能顺序处理,llama.cpp 也不是只能自行封装单用户进程。当前官方文档分别说明了 Ollama 并行请求,以及 llama-server 的并行解码与连续批处理。反过来,vLLM 更强的调度能力也不保证在所有模型和负载下拥有更低延迟或成本。

按工作负载选型,而不是按用户数口号

选型应由主要约束和实际运维责任决定。

工作负载 建议起点 原因 采用前必须证明
笔记本 Prompt 调试与本地应用开发 Ollama 模型获取、生命周期和本地 API 已集成 模板、上下文、结构化输出和交互延迟正确
CPU、Apple Silicon、边缘或自定义设备 llama.cpp 或 Ollama GGUF 与广泛本地后端是核心能力 目标设备上的质量、功耗、内存和温度
单 GPU 内部 API 与中等共享负载 同时测试 Ollama 与 vLLM 两者都可能适用,排队与模型工作流可能更重要 尾延迟、过载行为、内存余量和运维成本
变长请求的共享 GPU 服务 优先把 vLLM 纳入候选 连续调度与分页缓存针对该类负载 真实到达率下的 Goodput、抢占与质量一致性
模型超出单个加速器容量 vLLM 或经过验证的 llama.cpp 分片 需要显式多设备拓扑 模型装载、互联开销、启动日志和故障恢复
多节点推理服务 三者中优先评估 vLLM 有明确张量/流水线并行路径 私有网络、拓扑基准、故障处理和回滚
固定 GGUF 制品的嵌入式产品 llama.cpp 部署面小且运行时控制直接 可复现构建、制品来源和端侧验收测试

不要把表格退化为“5 个用户就必须上 vLLM”。5 个长上下文请求可能比数百个短请求更耗内存;当到达率低于服务能力时,批处理甚至不会形成。容量规划应该看 Token 与时间,而不是“用户”这个标签。

并发、排队与 KV Cache

并发会增加常驻 Token 状态,因此上下文长度与并行请求必须一起规划。KV Cache 容量指南解释了为什么仅看模型权重无法预测服务容量。

Ollama 的并发边界

Ollama FAQ 明确说明,在内存允许时可以并行处理单个模型的请求。OLLAMA_NUM_PARALLEL 控制单模型最大并行请求数,内存需求随并行度与上下文长度的乘积增长;OLLAMA_MAX_QUEUE 控制过载拒绝前的排队上限。Ollama 还可以同时驻留多个模型;当模型无法装入单个 GPU 时,可能分布到可用 GPU。

这些能力不等于 vLLM 的调度器或分布式执行模型。必须在目标主机观察 ollama ps、请求时间、拒绝行为、处理器放置与真实常驻内存。

vLLM 的调度边界

vLLM 将服务调度器与分页 KV Cache 分配结合。其并行指南区分单 GPU、单节点张量并行,以及跨节点张量并行加流水线并行。启动日志会报告可用 KV Cache 容量与估算最大并发,但这是容量信号,不是应用 SLO。

PagedAttention 原论文报告的收益只适用于论文中对比的系统、模型与工作负载,不能转换成当前 vLLM 相对当前 Ollama 的固定倍数。合理做法是把分页视为减少碎片和重复的机制,再按真实序列分布测量效果。

llama.cpp 的服务边界

llama-server 官方文档包含并行解码、多用户、slot、连续批处理、缓存控制、指标、API Key 和多设备 split。llama-bench 则单独测量 Prompt Processing 与 Text Generation,并明确不包含 Tokenization 和 Sampling。前者用于服务评测,后者用于隔离运行时变化,不能混为同一个延迟指标。

先建立模型与量化等价性

如果换了模型后响应更快,这不是服务优化。对比前至少固定:

  • 源模型与不可变权重修订;
  • Tokenizer 文件与修订;
  • Chat Template 与特殊 Token;
  • Adapter 和权重合并状态;
  • 量化方法、校准数据与制品校验和;
  • 上下文与 RoPE 配置;
  • 生成默认值、停止规则、随机种子和结构化输出策略。

Ollama 与 llama.cpp 常使用 GGUF,vLLM 常服务其他仓库格式与量化方案。即使制品来自同一个基础 Checkpoint,不同量化也可能改变指令遵循、工具调用、结构化输出、长上下文行为与 Token 概率。性能对比前必须先通过业务质量集。

模型量化指南说明了格式与精度权衡。不要引用统一的“保留 98% 质量”:结果始终依赖模型、量化器、校准、任务和指标。

OpenAI 兼容必须作为协议契约测试

“OpenAI 兼容”表示协议家族,不表示行为完全等价。Ollama 官方措辞是支持 OpenAI API 的部分能力;vLLM 文档列出了支持的 API、不支持或忽略的参数、Chat Template 要求和引擎扩展字段。llama-server 同样提供兼容路由,但支持范围与语义需要独立核对。

迁移契约至少覆盖:

契约区域 验证内容
服务发现 模型列表、服务模型名、别名与修订可见性
请求 Endpoint、Role、内容类型、Stop、Tool、Response Format 与不支持参数
模板 最终渲染 Prompt、特殊 Token、缺少 Chat Template 时的行为
生成 Temperature/Top-p 默认值、Seed、最大 Token 与服务端 Generation Config
流式 Event 帧、终止事件、usage 位置、断连与取消
响应 Finish Reason、Tool Call、Logprobs、Token 计数和 Request ID
失败 鉴权、非法输入、过载、超时、模型不存在与是否可重试
运维 健康/就绪、指标、日志脱敏、优雅退出与流量排空

只有这组用例通过后,改 base_url 才是可接受的最后一步。端点可访问并不能证明 Prompt、输出、计费或错误语义一致。

可复现的基准测试契约

有效的本地大模型基准必须复现生产到达过程,同时报告延迟与“按时完成的有效工作”。每份结果都应保存以下 Manifest:

yaml
benchmark:
  hardware:
    accelerator: "精确型号与数量"
    interconnect: "PCIe、NVLink 或无"
    cpu_ram_storage: "记录完整配置"
  software:
    os_driver_runtime: "不可变版本"
    engine_revision: "Tag 或 Commit"
  model:
    source_revision: "不可变修订"
    tokenizer_revision: "不可变修订"
    artifact_sha256: "校验和"
    quantization: "方法与参数"
    chat_template_sha256: "校验和"
  workload:
    prompt_tokens: "分布,而非只有平均值"
    output_tokens: "分布,而非只有上限"
    prefix_reuse: "分布"
    request_rate: "每秒请求数与到达模型"
    max_concurrency: "客户端并发上限"
    warmup_requests: "预热请求数"
  generation:
    temperature: 0
    seed: 42
    stop_policy: "固定策略"
  slos:
    ttft_ms_p95: "应用目标"
    itl_ms_p95: "应用目标"
    e2e_ms_p95: "应用目标"

至少测量:

  • TTFT、ITL 或 TPOT、端到端延迟的 p50/p95/p99;
  • 请求吞吐与输出 Token 吞吐;
  • 成功、超时、取消和过载拒绝率;
  • 满足 SLO 的 Goodput;
  • 可用时记录排队、Prefill、Decode和抢占;
  • 模型、KV Cache、Activation、主机内存与设备内存;
  • 业务质量与结构化输出合法率;
  • 将启动、模型加载与恢复作为独立冷路径指标。

vLLM 的 bench serve 可控制请求到达率、突发度、最大并发、预热、输入输出长度、分位指标与 Goodput SLO。Ollama 原生生成响应拆分模型加载、Prompt Evaluation 与 Token Generation 时间。llama-bench 拆分 Prompt Processing 与 Generation,但不含 Tokenization 与 Sampling。三者测量边界不同,因此公平比较仍需统一的外部压测器。

计算满足 SLO 的 Goodput

Goodput 只统计满足应用 SLO 的完成请求,避免系统通过接收大量迟到请求“做高吞吐”。下面的无依赖脚本读取归一化 JSONL Trace:

python
from __future__ import annotations

import json
import sys
from pathlib import Path


REQUIRED = ("ok", "ttft_ms", "itl_p95_ms", "e2e_ms")


def load_traces(path: Path) -> list[dict]:
    traces = []
    with path.open(encoding="utf-8") as handle:
        for line_number, line in enumerate(handle, start=1):
            if not line.strip():
                continue
            try:
                trace = json.loads(line)
            except json.JSONDecodeError as error:
                raise ValueError(f"line {line_number}: invalid JSON") from error
            missing = [key for key in REQUIRED if key not in trace]
            if missing:
                raise ValueError(f"line {line_number}: missing {missing}")
            traces.append(trace)
    if not traces:
        raise ValueError("trace file is empty")
    return traces


def goodput(traces: list[dict], duration_s: float) -> tuple[int, float]:
    if duration_s <= 0:
        raise ValueError("duration_s must be positive")
    passed = sum(
        bool(trace["ok"])
        and float(trace["ttft_ms"]) <= 800
        and float(trace["itl_p95_ms"]) <= 80
        and float(trace["e2e_ms"]) <= 5000
        for trace in traces
    )
    return passed, passed / duration_s


try:
    source = Path(sys.argv[1])
    duration = float(sys.argv[2])
    count, requests_per_second = goodput(load_traces(source), duration)
    print(f"SLO-passing requests: {count}")
    print(f"Goodput: {requests_per_second:.2f} requests/s")
except (IndexError, OSError, ValueError) as error:
    raise SystemExit(f"usage: python goodput.py TRACE.jsonl DURATION_S\n{error}") from error

所有引擎必须使用相同事件边界。服务原生指标可以补充 Trace,但不能悄悄改变 Arrival、First Token、Last Token 与 Completion 的定义。LLM 推理指南进一步解释了这些测量边界。

基线有效后再调优

调优应每次只改变一个受控维度。

Ollama 调优顺序

  1. 固定模型,并用 ollama ps 查看真实处理器放置。
  2. 只配置业务需要的上下文长度。
  3. 逐步增加并行度,同时观察内存、排队与拒绝。
  4. 在支持的硬件上测试 Flash Attention 与 KV Cache 类型。
  5. 按复用率和加载延迟设置模型驻留时间。

vLLM 调优顺序

  1. 确认模型可装载,并记录启动日志中的 KV Cache 容量。
  2. 修改调度上限前,先建立请求到达率曲线。
  3. 长 Prompt 干扰 Decode 时再评估 Chunked Prefill。
  4. 只有在前缀复用分布真实时才评估 Prefix Caching。
  5. 根据模型装载与拓扑选择张量/流水线并行,并测量通信开销。
  6. 跟踪 Queue、KV Usage、TTFT、ITL、E2E、Preemption 与 Request Success。

llama.cpp 调优顺序

  1. 固定 Build Commit、Backend、GGUF 校验和、Thread 与设备放置。
  2. 用 llama-bench 分开测试 Prompt Processing 与 Token Generation。
  3. 分别调整 Batch、Micro-batch、Cache Type、Context 与 Offload。
  4. 配置 Server Slot 与 Continuous Batching,再执行 HTTP 负载测试。
  5. 在边缘设备复查功耗、温度和持续性能。

投机解码、缓存量化与激进批处理都是实验变量,不是固定倍数。只有在不破坏质量与尾延迟门禁、且确实提高目标 Goodput 时才保留。

生产安全与运维边界

模型在本地运行只改变数据路径,不会自动满足隐私、安全或合规要求。生产边界仍需具备:

  • 开发机只绑定 Loopback,服务端进入受控私有网络;
  • 网关鉴权、授权、TLS、请求大小限制与限流;
  • 租户感知队列、缓存隔离与日志脱敏;
  • 模型制品 Allowlist、校验和、许可证与来源记录;
  • 健康/就绪探针、Load Shedding、超时、取消和优雅排空;
  • 默认不持久化敏感 Prompt 的审计事件;
  • 固定镜像或 Commit、分阶段发布与经过演练的回滚;
  • 多节点内部流量使用私有网络,因为分布式引擎流量不能默认安全地暴露到不可信网络。

Ollama 默认绑定本地地址,但修改绑定地址后,如果没有外部安全边界,就可能暴露未鉴权服务。llama-server 支持 API Key,但 Key 校验本身不等于租户隔离或传输安全。vLLM 指标很有价值,但指标名也有引擎生命周期,应与部署修订一起固定。

迁移与回滚门禁

只有模型行为、协议行为和运维行为全部通过,迁移才算完成。

  1. 冻结身份:记录源修订、Tokenizer、Template、Quantizer、Checksum 与生成默认值。
  2. 质量对齐:比较业务任务分数、结构化输出、工具调用、拒答与长上下文行为。
  3. API 对齐:重放成功、非法、流式、取消和过载请求。
  4. 负载验证:扫描到达率与上下文/输出分布,找到 SLO 饱和点。
  5. 运维验证:鉴权、指标、Trace、脱敏、Readiness、Drain、Restart 与模型加载。
  6. 灰度:按受控 Cohort 路由,为指标标记 Backend,禁止静默回退。
  7. 回滚:保留旧制品、配置、路由规则和恢复所需状态。

“开发用 Ollama、生产用 vLLM”的混合模式可以成立,但只有两端固定兼容模型契约时才不会产生环境漂移。若模板、量化或默认参数不同,快速本地原型就不是生产预演。

常见失败模式

最昂贵的故障通常来自无效对比或失控边界。

现象 常见根因 应补充的证据
Token/s 很高但聊天体验差 排除了 Prompt Processing、Queue 或网络时间 TTFT、ITL、E2E 与统一事件 Trace
迁移后质量下降 制品、模板、Tokenizer、量化或默认值不同 身份 Manifest 与业务质量对齐集
只有并发时出现 OOM 上下文乘并行序列超过缓存预算 Resident Token Slots、Cache Usage 与队列上限
中位数正常但 p99 抖动 突发排队或长 Prefill 干扰 Offered-load 曲线、Queue Time、Prompt 分布与抢占
“兼容”客户端报错 Field、Template、Stream、Usage 或 Error 不兼容 协议一致性用例
多 GPU 反而更慢 通信与拓扑开销占主导 分拓扑基准与设备/互联 Trace
本地端点泄漏数据 服务无网关、TLS 或日志脱敏 网络清单、鉴权测试与日志审计

一手资料

常见问题

vLLM 一定比 Ollama 快吗?

不一定。vLLM 面向高吞吐加速器服务,但实际性能取决于模型、量化、硬件、请求长度、到达负载和 SLO。Ollama 在本地工作流中可能有更低运维成本。应在质量通过后比较 Goodput 和尾延迟,而不是引用孤立 Token/s。

Ollama 能并行处理请求吗?

可以。Ollama 通过 OLLAMA_NUM_PARALLEL 在内存允许时为单模型配置并行请求,并提供有界队列。并行度会放大上下文相关内存,因此必须测试具体模型、上下文和主机,不能假设固定并发上限。

llama.cpp 能服务多个用户吗?

可以。官方 llama-server 支持并行 Slot 与连续批处理。应使用 llama-bench 隔离核心运行时性能,并用独立的流式 HTTP 压测验证 Queue、TTFT、Cancellation、Error 与端到端多用户行为。

OpenAI 客户端能在 Ollama 与 vLLM 之间零改动迁移吗?

只有协议一致性用例通过后才能这样做。兼容端点不保证参数、Chat Template、模型名、默认值、流式事件、usage 与错误完全一致。固定这些行为后,切换 base_url 才是最后的路由动作,而不是完整迁移方案。

哪些指标能决定本地大模型服务选型?

先把业务质量设为硬门槛,再按真实到达负载比较 TTFT、ITL 或 TPOT、E2E、输出 Token 吞吐、错误、排队、内存和 SLO 合格 Goodput。冷启动与恢复时间单独统计。最终选择应同时满足工作负载 SLO、成本与运维能力。

总结

Ollama、vLLM 与 llama.cpp 是本地大模型推理的三种不同运维答案。先确定工作负载、模型身份、硬件、API 与安全契约,再测量真实到达率和满足 SLO 的 Goodput。若 Ollama 的集成工作流与实测容量足够,就不必增加复杂度;若调度与分布式 GPU 服务经过验证能产生价值,再选择 vLLM;若可移植性与运行时控制更重要,则选择 llama.cpp。模型、上下文、量化、引擎或硬件变化后,都应基于固定制品与 Trace 重新评估。