GPUFits

GGUF 本地部署实操:llama.cpp 与 Ollama 两条路径

更新于 2026-09-10 · 核实于 2026-09-10

下载一个 GGUF 文件、跑起来、看一眼速度——听起来三步的事,卡住大多数人的是中间没说清的部分:一排量化文件名选哪个、-ngl 到底设多少、为什么「能跑」但慢得像打字机。这篇把 llama.cpp 和 Ollama 两条路径从头到尾走一遍,每个数字都给出算法,跑完之后怎么验证也讲清楚。

动手之前:先算显存

错误的顺序是「先下载,装不下再说」。一个 70B 的 Q4 文件 43GB,下到一半才发现装不下,浪费的是一小时带宽。正确的第一步是算账。本站显存计算器用的公式:

总显存 = 参数量(十亿) × bit/权重 ÷ 8    ← 权重,≈ GGUF 文件体积
       + KV 缓存(随上下文线性增长)
       + 约 1.5GB 运行时开销

bit/权重取实测 GGUF 文件反推值:Q4_K_M 约 4.9、Q6_K 约 6.6、Q8_0 约 8.5。按 8K 上下文、fp16 KV 缓存算几个常见组合:

模型 × 量化权重KV @8K总量能装下的卡
Llama-3.1-8B Q4_K_M4.9GB1.1GB7.5GBRTX 3060 12GB,宽裕
Llama-3.1-8B Q8_08.5GB1.1GB11.1GB12GB 勉强,16GB 宽裕
Qwen3-32B Q4_K_M20.1GB2.1GB23.7GB单张 24GB(3090/4090),勉强
Llama-3.3-70B Q4_K_M43.2GB2.7GB47.4GB2× 24GB 或 48GB 卡
Qwen3-30B-A3B(MoE)Q4_K_M18.7GB0.8GB21.0GB单张 24GB

判定标准:总量 ≤ 可用显存 80% 为宽裕,≤100% 为勉强。想在下载前确认自己的卡能跑哪个档,用显卡检查器直接查,它和本文是同一套公式。

量化档怎么选

Hugging Face 上 bartowski 等仓库的同一个模型会挂出一排文件:Q8_0Q6_KQ5_K_MQ4_K_MQ3_K_M……三条规则就够:

  • 默认 Q4_K_M。 体积约 FP16 的 30%,对话和写作场景盲测基本分不出与 Q8 的差别。它是社区的默认档不是没有原因的。
  • 显存富余就往上升: Q6_K、Q8_0。数学、长推理链、Agent 工具调用这类对权重噪声敏感的任务值得升档。
  • Q4 到 Q3 是悬崖。 Q3_K_M 开始丢事实、前后矛盾;Q2 只剩「能出字」。装不下时的正确解法通常是换更小的模型,不是把大模型压到 Q2。完整对比见量化详解

路径 A:llama.cpp

llama.cpp 是这一切的底层引擎——Ollama、LM Studio 都跑在它之上。从 GitHub releases 下载预编译包(或源码编译),得到 llama-clillama-server 等可执行文件。

下载 GGUF

两种方式:从 Hugging Face 页面手动下载对应档位的 .gguf 文件;或者直接用内置的 -hf 参数让 llama.cpp 自己拉:

llama-cli -hf bartowski/Meta-Llama-3.1-8B-Instruct-GGUF:Q4_K_M

8B 的 Q4_K_M 约 4.9GB,普通宽带几分钟。注意大模型的 GGUF 常拆成多个分卷,要全部下载放在同一目录。

三个关键参数

-ngl(—n-gpu-layers):放上显卡的层数。 这是 llama.cpp 最重要的参数,没有之一。-ngl 32 把 32 层全部上卡(Llama-3.1-8B 正好 32 层);-ngl 99 表示「能放多少放多少」,显存满了剩下的层自动落回 CPU 用系统内存跑——这就是部分卸载(partial offload),技术上完全可行,但生成速度会被拖到系统内存带宽档位:全量在 4090 上约 154 tok/s 的 8B Q4,部分卸载的下限只有个位数(理论估算 ±30%)。它适合「跑一夜看结果」的批量任务,不适合聊天。机制和决策边界见 CPU 卸载指南

--ctx-size:上下文长度。 它直接决定 KV 缓存占多少显存。Llama-3.1-8B 开 8K 时 KV 约 1.1GB,开到 32K 涨到 4.3GB,总量从 7.5GB 变 10.7GB——本来宽裕的配置会变成顶格。显存吃紧时先想清楚自己到底需要多长上下文,别默认开满。

--cache-type-k q8_0 --cache-type-v q8_0:KV 缓存量化。 把 KV 缓存从 fp16 压到 8 bit,占用减半,质量损失极小。上下文吃紧时这是第一逃生通道,优先级高于降权重量化档。细节见 KV 缓存指南

一条典型的完整命令:

llama-cli -m Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf -ngl 99 --ctx-size 8192

想要 API 服务而不是交互命令行,把 llama-cli 换成 llama-server,会起一个兼容 OpenAI 格式的本地接口。

启动日志就是验收单

llama.cpp 启动时会打印每一层的去向(GPU/CPU)、权重和 KV 缓存的实际 VRAM 分配。养成看一眼的习惯:日志里的分配值应该和你按公式估的总量对上量级;对不上,先查 --ctx-size 是不是和你假设的不一样。

路径 B:Ollama

Ollama = llama.cpp + 模型仓库 + 服务管理 + 自动更新。安装后一条命令:

ollama run llama3.1:8b

它会自动下载官方库里对应的 GGUF(默认通常是 Q4_K_M 档位)并进入交互会话。模型默认加载后驻留几分钟,空闲超时自动卸载。

导入自己的 GGUF

想用 Hugging Face 上的某个特定量化档,写一个 Modelfile:

FROM ./Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf
PARAMETER num_ctx 8192

然后 ollama create my-llama -f Modelfile 注册,ollama run my-llama 运行。

两个和 -ngl / —ctx-size 对应的参数

  • num_ctx(上下文):Ollama 的默认值是 4096(Modelfile 官方文档),比模型标称的上下文窗口小得多。这是「我按 8K 算的显存,怎么实测这么小」和「长文档为什么丢前文」两个高频问题的共同答案。交互会话里用 /set parameter num_ctx 8192,或写进 Modelfile,新版本也支持环境变量 OLLAMA_CONTEXT_LENGTH
  • num_gpu(上卡层数):等价于 llama.cpp 的 -ngl,写进 Modelfile 如 PARAMETER num_gpu 99。日常不用动——Ollama 默认会尽量全量上卡,装不下才自动部分卸载,而这个行为恰恰需要你主动去发现。

ollama ps:一眼看穿部署状态

ollama ps

输出里的 SIZE 是模型当前占用的显存+内存总量,PROCESSOR 是关键的一列:100% GPU 表示全量在卡上;出现 48%/52% CPU/GPU 这样的比例,说明部分层落到了内存——能跑,但速度会掉到个位数 tok/s。这条命令和 nvidia-smi 配合使用,是排查「为什么慢」的第一现场。

跑完之后:验证显存与速度

部署完成不等于部署正确。两个验收动作:

验证实际显存占用。 N 卡用 nvidia-smi 看进程占用;Ollama 用 ollama ps;llama.cpp 看启动日志的分配行。实测值和公式估算差得远时,按这个顺序排查:① 运行时默认上下文比你假设的小(Ollama 默认 4096);② KV 缓存被量化成了 q8;③ 部分层在内存里。

验证 tok/s。 llama.cpp 每轮生成结束会打印 eval time 和 tokens per second;Ollama 加 --verbose 标志,结束时会输出 eval rate。把实测值和理论估算对比——按本站速度模型:

理论 tok/s ≈ 显存带宽 × 0.75 ÷ 每 token 读取的权重 GB

参考锚点(理论估算 ±30%,实际受框架、驱动、CPU 影响):

硬件模型 × 档位理论速度【估】
RTX 3060(360 GB/s)8B Q4_K_M约 55 tok/s
RTX 4090(1008 GB/s)8B Q4_K_M约 154 tok/s
RTX 3090(936 GB/s)32B Q4_K_M约 35 tok/s
2× RTX 309070B Q4_K_M约 28 tok/s
RTX 4090Qwen3-30B-A3B(MoE,每 token 只读 2.0GB)约 374 tok/s

实测在理论值的 0.7–1.3 倍区间里都算正常;差一个数量级,几乎必然是部分卸载了——回去查 ollama ps 或启动日志。另一个经验值:交互聊天低于约 10 tok/s 会明显烦躁,20+ 是流畅,这时该考虑降量化档、缩短上下文或换小模型。

常见误区

  • 「下载了就跑,参数不用管。」 默认值到处埋雷:Ollama 的 num_ctx 默认 4096,长文档场景会在你不知情时截断;显存装不下时 Ollama 静默部分卸载,表现为「能跑但巨慢」。
  • 「-ngl 设一半,速度减半而已。」 不是线性衰减,是断崖:只要最慢一环变成系统内存(60–100 GB/s),整个流水线按内存的节奏走,从三位数掉到个位数。
  • 「显存占用应该约等于文件大小。」 文件 ≈ 权重,还要加 KV 缓存和约 1.5GB 开销。8B 模型开 128K 上下文时 KV 约 17GB,是 Q4 权重的三倍多。
  • 「Ollama 和 llama.cpp 速度差很多。」 底层是同一个引擎,同模型同档位同参数下速度基本同源。差距来自参数默认值不同,不是引擎。
  • 「tok/s 低就是卡不行。」 先看是不是部分卸载、上下文开满、或在跑 prefill 重的任务。纯解码速度由显存带宽决定,同一张卡上 Q4 一定比 Q8 快。

一句话结论

先用显存计算器算出能装下的最高量化档,下载 Q4_K_M 起步;llama.cpp 路线记住 -ngl 99--ctx-size,Ollama 路线记住 num_ctxollama ps;跑完用启动日志和 tok/s 对照理论估算验收——对不上量级,九成是部分卸载了。

常见问题

llama.cpp 和 Ollama 该选哪个?

Ollama 底层就是 llama.cpp,速度基本同源。想省心选 Ollama:自带模型仓库、服务管理和 API。想完全掌控选 llama.cpp:每个参数(-ngl、上下文、KV 量化)都能显式指定,新特性也先到 llama.cpp。

llama.cpp 的 -ngl 应该设多少?

设为模型层数(如 Llama-3.1-8B 是 32 层)等于全量上显卡;设一个超过层数的大值(如 99)等于「能放多少放多少」,放不下的层自动落回 CPU。但部分卸载会让生成速度塌缩到系统内存带宽档位,只能当应急手段。

GGUF 文件名里一堆后缀,Q4_K_M、Q5_K_M、Q8_0 怎么选?

默认抓 Q4_K_M——体积约是 FP16 的 30%,质量在对话场景盲测难分。显存富余升 Q6_K 或 Q8_0,装不下才考虑 Q3。避开老式的 Q4_0 和激进的 IQ2/Q2 档,除非你知道自己在做什么。

为什么实际显存占用比 GGUF 文件大?

文件体积约等于权重显存,但运行还要加 KV 缓存和约 1.5GB 运行时开销。KV 缓存随上下文线性增长:Llama-3.1-8B 在 8K 上下文约 1.1GB,128K 时约 17GB。反过来,如果你按 8K 估的值比实测大,先查运行时的默认上下文——Ollama 默认只有 4096。

怎么确认模型全部跑在显卡上,没有偷跑到内存?

Ollama 用 ollama ps 看 PROCESSOR 列,「100% GPU」才是全量上卡,「48%/52% CPU/GPU」这类比例就是部分卸载;llama.cpp 看启动日志里每层的去向和 VRAM 分配行。部分卸载时 tok/s 会直接掉到个位数,速度本身就是最诚实的信号。

来源