项目: llama.cpp — 社区驱动的 C/C++ 推理引擎,GGUF 格式的事实标准
前置阅读: 大模型量化系列 · GPTQ · AWQ
参考: K-Quant PR #1684 · Importance Matrix PR #4861 · 2-bit I-Quant PR #4897 · 统一评测 arXiv:2601.14277

一句话总结: llama.cpp 的 GGUF 量化不是单一算法,而是一套面向本地部署的格式族——Legacy 块量化打底,K-Quant 用 super-block 分层混合精度把 4 bit 做稳,I-Quant 再靠 Importance Matrix 和非线性映射把 2–3 bit 从「不可用」拉到「能跑」。

一、为什么需要单独讲 llama.cpp 量化

大模型量化系列里我们聊过 LLM.int8()、GPTQ、AWQ——它们的目标大多是 W8A8 或 W4A16 的 GPU 推理,评估也集中在 PyTorch 生态。

llama.cpp 走的是另一条路:

1
2
3
目标:在 CPU / Apple Silicon / 混合 offload 上跑开源 LLM
手段:离线 weight-only PTQ → GGUF 文件 → mmap 零拷贝加载
特点:格式多、迭代快、社区驱动,没有一篇「官方论文」

Ollama、LM Studio、koboldcpp、text-generation-webui 的 GGUF 后端,底层都是 llama.cpp。你在 Hugging Face 下载的 Q4_K_M.ggufIQ4_XS.gguf,文件名里的字母组合就是本文要讲的内容。

GPTQAWQ 的本质区别:

维度 GPTQ / AWQ llama.cpp GGUF
量化时机 PTQ,带 Hessian 补偿或 activation-aware 缩放 PTQ,主要是 block-wise 取整 + 格式工程
运行时 需要 CUDA kernel(AutoGPTQ、vLLM 等) CPU/GPU/Metal 通用,activation 保持 FP16/FP32
格式 单一 bit-width 十几种格式,按 tensor 混合精度
选型依据 论文 + benchmark perplexity + 社区经验 + 近期系统评测

这不是说 GGUF 量化「更差」——它在 本地部署、跨硬件、磁盘/内存受限 场景里往往是唯一合理选择。难点在于:名字太多,该选哪个?


二、共同基础:Block-wise Affine 量化

不管 Legacy、K-Quant 还是 I-Quant,llama.cpp 都是 weight-only PTQ:权重离线压成整数,推理时 activation 仍用浮点(部分 kernel 内部会临时量化 activation 做 dot product,但对用户透明)。

每个 weight block 存一组 scale(有时还有 offset/min),反量化公式:

Legacy 格式把权重切成 32 个一组 的 block,每个 block 一个 scale:

1
2
3
4
5
Legacy 家族(2023 年初):
Q4_0 — 对称 4 bit,无 zero-point,$q \in [-8, 7]$
Q4_1 — 仿射 4 bit,存 scale + min/offset,适应非对称分布
Q5_0 / Q5_1 — 5 bit 对称/仿射
Q8_0 — 8 bit 对称,接近 FP16 的高保真 baseline

名义上都是 4 bit,但 Q4_0 和 Q4_1 只有 一个 block 级 scale,对 outlier 和跨 block 动态范围差异很敏感。社区很快发现:同样叫「4 bit」,Legacy 和 K-Quant 的质量差距可以很大。


三、K-Quant:Super-Block + 跨 Tensor 混合精度

K-Quant 由 ikawrakow 在 2023 年中通过 PR #1684 引入,是当前 ≥4 bpw 场景的事实默认

1. Super-Block 结构

K-Quant 把 256 个 weight 组成一个 super-block,再切成若干 sub-block。以 Q4_K 为例:

1
2
3
4
Super-block(256 weights)
├── 8 个 sub-block,每个 32 weights
├── sub-block 各自有 scale / min(本身也量化,通常 6 bit)
└── 有效 bpw ≈ 4.5(不是整数 4!)

相比 Legacy 的 32-weight block,K-Quant 多了一层 hierarchy:super-block 管全局动态范围,sub-block 管局部细节。同样 4 bit 名义宽度,重建误差显著更小。

各 K-Quant 变体的 bpw 大致如下(来自社区文档与 Discussion #559):

格式 有效 bpw 说明
Q2_K ~2.56–3.0 2 bit 为主,部分 tensor 用 3 bit
Q3_K_S / M / L ~3.4 / 3.5 / 3.6 S=压缩优先,L=质量优先
Q4_K_S / M ~4.2 / 4.5 M 是社区最常用默认
Q5_K_S / M ~5.2 / 5.5 接近无损
Q6_K ~6.5 高质量,体积仍比 FP16 小 ~40%

后缀 S / M / L 不是「模型大小」,而是 同一 bpw 档位内的压缩–质量 trade-off:S 更省空间,L 给敏感 tensor 更多 bit。

2. 跨 Tensor 混合精度(这才是 Q4_K_M 的精髓)

K-Quant 的名字容易让人以为只是「block 结构升级」。真正拉开差距的是:不同 tensor 可以用不同的 K-Quant 子格式

Q4_K_M 为例(Llama-3.1-8B 上约 4.58 GiB,bpw ≈ 4.89):

1
2
Q4_K 用于:token_embd、attn_q、attn_k、ffn_gate、ffn_up、attn_output
Q6_K 用于:attn_v、ffn_down(各取一半)

直觉上,attn_vffn_down 对输出质量更敏感——给它们 6 bit,其余 4 bit,整体 bpw 只比纯 Q4_K 高一点点,perplexity 却接近 Q5。

Q4_K_S 则所有 tensor 统一用 Q4_K,文件更小(~4.2 bpw),质量略逊。Q4_K_M 用混合精度换质量,是 bartowski 等量化发布者推荐的默认档。

3. K-Quant 的局限

Super-block 要求 tensor 列数能被 256 整除。早期 Falcon-7B、OpenLLaMA-3B 等模型部分 tensor 不满足,只能回退到 Legacy 格式(Issue #1919)。后续 row-wise 量化(IQ 系列的一部分)部分缓解了这个问题。


四、I-Quant:Importance Matrix + 超低 bit

2024 年初,ikawrakow 在 K-Quant 基础上推出 I-Quant(Importance-matrix Quantization),目标是把有效 bpw 压到 2–4 bit 区间,同时保持可用质量。

I-Quant 和 K-Quant 是 并列的两套方案,不是简单的「K-Quant 升级版」:

1
2
K-Quant:super-block + 跨 tensor 混合精度,≥4 bpw 的主力
I-Quant:importance matrix 加权 RMSE + 非线性映射 + 更激进的 block 设计,主攻 2–3 bpw

1. Importance Matrix(imatrix)是什么

PR #4861 引入的核心思想:量化一行 weight 时,不同 column 对 layer output 的贡献不同,应该 按重要性加权 最小化重建误差。

对 tensor 某一行 ,输入 activation 为 ,量化后希望最小化:

求导,在 calibration data 上取期望,近似为按 加权——这就是 importance matrix:每个 hidden dimension 一个标量,表示该维度 activation 的期望能量。

1
2
高 ⟨a_i²⟩  →  对应 weight 更重要  →  量化时分配更多精度
低 ⟨a_i²⟩ → 可以更激进地压缩

生成 imatrix 的工具是 llama-imatrix

1
2
3
4
5
# 1. 准备与目标任务相关的 calibration 文本(wiki 通用,但领域文本更好)
./llama-imatrix -m model-f16.gguf -f calibration.txt -o imatrix.dat -ngl 99

# 2. 量化时传入
./llama-quantize --imatrix imatrix.dat model-f16.gguf model-q4_k_m.gguf Q4_K_M

关键区分(社区常混淆):

  • imatrix 是一种校准数据,K-Quant 和 I-Quant 都可以 用它提升质量
  • I-Quant 格式(IQ2_XXS、IQ3_M 等)在 极低 bit必须 依赖 imatrix,否则质量崩溃
  • 对 Q4_K_M,加 imatrix 通常只有 ~0.5% 量级改善;对 IQ2_XXS,改善可达 50%+

2. I-Quant 格式族

I-Quant 命名规则:IQ{bit}_{size}

1
2
bit 档位:IQ2、IQ3、IQ4、IQ5、IQ6 …
size 后缀:XXS < XS < S < M < NL < K …(越小越压缩,bpw 越低)

常见格式及定位:

格式 有效 bpw 典型体积(8B 模型) 定位
IQ2_XXS ~2.06 ~2.5 GiB 极限压缩,必须 imatrix
IQ2_XS / IQ2_S ~2.3–2.5 ~2.8 GiB 2 bit 可用档
IQ3_XXS / XS / S / M ~3.0–3.7 ~3.5–4.7 GiB 3 bit 主力
IQ4_XS ~4.25 ~4.17 GiB 比 Q4_K_M 更小,需 imatrix
IQ4_NL ~4.0 非线性 4 bit,block=32/64

I-Quant 还引入了 Legacy/K-Quant 没有的机制(Discussion #5063):

  1. 非线性映射,用 3 阶多项式替代线性 scale,同样 bpw 下重建误差更小
  2. Row-wise scale:每行一个 scale,解决 tensor 列数非 256 整除的问题
  3. k-means 聚类量化(IQ4_NL 等):权重映射到聚类中心而非均匀 grid

代价是 kernel 更复杂,decode 速度有时不如 K-Quant;但在 VRAM 不够、必须多塞几层到 GPU 时,更小体积带来的 offload 收益可以抵消 kernel 开销。

3. IQ4_XS vs Q4_K_M:4 bit 档位的两种哲学

两者都是「4 bit 级别」,设计思路不同:

1
2
3
4
5
6
7
8
9
10
11
12
Q4_K_M(K-Quant):
· 不强制 imatrix,开箱即用
· super-block + 跨 tensor Q4/Q6 混合
· ~4.89 bpw,质量稳定可预期
· 社区默认,兼容性最好

IQ4_XS(I-Quant):
· 强烈依赖 imatrix 质量
· 非线性映射 + 更激进压缩
· ~4.25–4.46 bpw,文件更小
· decode 有时更快,prefill 有时更慢
· 对 calibration 分布敏感

Llama-3.1-8B 上(Kaitchup 对比):IQ4_XS ~4.17 GiB vs Q4_K_M ~4.58 GiB,生成速度 IQ4_XS 略快,prompt 处理 Q4_K_M 略快。质量差距取决于 imatrix 是否与任务匹配。


五、Legacy / K-Quant / I-Quant 怎么选

arXiv:2601.14277 在 Llama-3.1-8B-Instruct 上做了目前最系统的 GGUF 格式对比(13 种 K-Quant + Legacy,FP16 baseline)。核心结论:

1. 质量–体积 Pareto 前沿

1
2
3
4
5
质量优先 + 仍要压缩:  Q5_0(Avg 甚至略高于 F16,体积 -65%)
均衡默认: Q4_K_S / Q4_K_M(Avg 接近 F16,体积 -69~71%)
再压一档: Q3_K_L / Q3_K_M(体积 -73~75%,质量可控下降)
极限压缩: Q3_K_S / IQ2_XXS(体积 -77%+,数学/推理任务明显退化)
几乎无损: Q6_K / Q8_0(体积 -47~59%,PPL 最接近 F16)

注意:5 bit 并不总是比 4 bit 好。Q5_0 在该评测中 aggregate 最高,但 Q5_K_S 反而不如 Q4_K_S——说明 格式设计比名义 bit-width 更重要

2. 按场景选型

场景 推荐格式 理由
日常聊天 / 通用本地部署 Q4_K_M 质量稳定、无需 imatrix、生态兼容最好
磁盘/内存极紧,仍要 4 bit IQ4_XS + 好 imatrix 比 Q4_K_M 小 ~10%,需校准
数学 / 多步推理 Q5_0Q4_K_S GSM8K 对 3 bit 最敏感
指令遵循敏感 Q4_K_S / Q5_0 IFEval 在 mid-bit K-Quant 上甚至略超 F16
VRAM 只够 2–3 bit IQ3_M / IQ2_XS + imatrix 不用 imatrix 基本不可用
质量接近 FP16 Q6_K / Q8_0 PPL delta < 0.05
纯 CPU 吞吐优先 Q3_K_S / Q4_K_M 低 bit → 高 tg128 tokens/s

3. 一张决策树

1
2
3
4
5
6
7
8
9
10
需要跑本地 LLM?
├── 有 NVIDIA GPU 且用 vLLM/TensorRT? → 考虑 AWQ/GPTQ(见量化系列)
└── CPU / Mac / 混合 offload / Ollama?
├── bpw ≥ 4?
│ ├── 求稳 → Q4_K_M
│ ├── 求小 + 愿意调 imatrix → IQ4_XS
│ └── 求质量 → Q5_0 / Q5_K_M / Q6_K
└── bpw < 4?
├── 3 bit → IQ3_M(+ imatrix)或 Q3_K_M
└── 2 bit → IQ2_XS / IQ2_XXS(imatrix 必须)

六、实操:从 HF 模型到 GGUF

1. 转换 + 量化流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 克隆 & 编译
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp && cmake -B build && cmake --build build -j

# HF → GGUF(F16 中间格式)
python convert_hf_to_gguf.py /path/to/hf-model --outfile model-f16.gguf

# 标准量化
./build/bin/llama-quantize model-f16.gguf model-Q4_K_M.gguf Q4_K_M

# 带 imatrix 的 I-Quant
./build/bin/llama-imatrix -m model-f16.gguf -f calib.txt -o imatrix.dat -ngl 99
./build/bin/llama-quantize --imatrix imatrix.dat \
model-f16.gguf model-IQ4_XS.gguf IQ4_XS

2. 验证

1
2
3
4
5
# Perplexity
./build/bin/llama-perplexity -m model-Q4_K_M.gguf -f wiki.test.raw

# 吞吐
./build/bin/llama-bench -m model-Q4_K_M.gguf

不要只看 PPL。统一评测 表明:PPL 接近的格式,在 GSM8K / IFEval 上可以差好几个点。最终格式应在你自己的任务上跑一轮。

3. imatrix 校准数据建议

1
2
3
4
通用对话  →  WikiText / C4 子集即可
代码 → The Stack / 自己的代码库
角色扮演 → 对应风格的对话语料
RAG/QA → 领域文档 + 问答对

imatrix 是 task-aware 的:用代码语料校准的 imatrix 量化出的模型,在代码任务上通常优于通用 wiki 校准。


七、和「学术量化」的关系

把 llama.cpp 量化放进 大模型量化系列 的脉络里:

1
2
3
4
5
LLM.int8()  →  发现 activation outlier
SmoothQuant → 把 outlier 从 A 迁到 W
GPTQ → 二阶补偿式 weight PTQ
AWQ → activation-aware 保护 salient weight
llama.cpp → 工程化 weight-only PTQ + 格式族,服务本地部署

llama.cpp 没有 GPTQ 的 Hessian 重构,没有 AWQ 的等价缩放——它的哲学是:

  1. Block-wise 仿射量化 足够简单,CPU SIMD / GPU kernel 都好写
  2. Super-block + 混合精度 用格式工程弥补简单取整的不足
  3. Importance Matrix 在极低 bit 下引入 activation 信息(和 AWQ 思路有呼应,但实现完全不同)
  4. 社区迭代:新格式通过 PR + perplexity + 下游任务反馈快速演进,而非等论文

这不是「学术 vs 工程」谁更好的问题——部署路径不同,选型就不同。有 CUDA 服务器跑 vLLM,AWQ/GPTQ 往往更快;要在 MacBook 或 8G 核显笔记本上跑 70B,GGUF + llama.cpp 几乎是唯一解。


参考资料