新计划:《GGUF 量化内幕:块量化、K-quants、码本与三值量化》

我打算写一本书,包含一系列文章来介绍 GGUF 格式中的大模型参数量化原理。

GGUF 量化技术之所以成为端侧大模型部署和大模型技术普及的关键基础设施,在于它把原本动辄数十GB、依赖高带宽显存和云端算力的模型权重,压缩到手机、笔记本、嵌入式设备可承受的存储与内存带宽范围内:通过 Q4_0、Q4_K、Q6_K、IQ 码本以及 STQ1/PTQ1 等三值格式的分层设计,GGUF 能在 1.5–6.5 bit/权重之间按张量敏感度灵活取舍,用块内尺度、超级块两级尺度、重要性矩阵和查表码本在显著减小体积的同时尽量保住模型质量,并借助 mmap 加载、逐张量混合精度和 llama.cpp 工具链实现“转换—量化—本地推理”的低门槛闭环;没有这类量化,端侧部署将受制于内存、功耗和成本而难以落地,大模型也只能停留在云端少数玩家的手中,正是 GGUF 量化让离线、低延迟、隐私可控的本地推理成为现实,从而推动大模型从集中式服务走向更广泛的技术普及。

全书大纲如下:


全书组织原则

主线:简单块量化 → K-quants 层次化量化 → IQ 码本量化 → 三值极限量化 → 混合精度与工具链 → 实现与性能 → 生态与演进。

每章统一结构:

  1. 问题:该格式要解决的误差/性能问题;
  2. 数学:量化/反量化公式与误差来源;
  3. 布局:字节级结构图与结构体;
  4. 代码:llama.cpp 关键函数走读 + 最小 Python 参考实现;
  5. 实验:PPL、KL、逐块误差、速度/内存基准;
  6. 陷阱:跨实现不兼容点与常见误读。

代码基线:锁定 llama.cpp/ggml 版本,所有 block_*、quantize_row_*、dequantize_row_*、vec_dot_* 引用标注版本。实验固定模型族、校准集与评测脚本。

篇幅:约 420–500 页,20 章 + 8 个附录。


第一部分 背景与基础

第 1 章 为什么需要 GGUF 量化

  • 1.1 模型分发、内存带宽与显存约束下的“体积—精度—速度”三角
  • 1.2 量化术语:bit/weight、块、超级块、尺度、最小值偏移、对称/非对称
  • 1.3 GGUF 在 llama.cpp 生态中的位置:转换、量化、mmap、推理
  • 1.4 量化范式的三次跃迁:仿射块量化 → 层次化尺度 → 码本/三值
  • 1.5 本书的实验方法与评价指标预告

第 2 章 数值基础与量化误差

  • 2.1 fp16/bf16/fp32 与定点表示的取舍
  • 2.2 仿射量化通式:(q=\mathrm{round}((x-z)/s)),(x=s(q-z))
  • 2.3 对称量化、非对称量化、块共享尺度的误差分析
  • 2.4 离群值为何是低比特量化的核心敌人
  • 2.5 第三种范式:重要性加权量化与码本反量化
  • 2.6 评价指标:MSE、最大相对误差、PPL、KL 散度、任务评测
  • 2.7 三值量化的特殊误差结构:阈值效应与任务退化

第 3 章 GGUF 容器与张量类型

  • 3.1 文件布局:header、tensor_infos[]、alignment、tensor data blob
  • 3.2 ggml_type 如何把量化决策下放到每个张量
  • 3.3 general.alignment 与 mmap 加载
  • 3.4 写一个最小 GGUF 解析器:读取张量名、形状、类型、偏移
  • 3.5 关键认知:Q4_K_M 文件内部是混合类型,不是全局单一格式
  • 3.6 ggml_type 全表:从 F32/Q4_0 到 IQ 系列、STQ1_0、PTQ1_0 的 type id 分布
  • 3.7 用 gguf-py 读写 GGUF:API 与示例
    • 3.7.1 安装与导入(pip install gguf、源码 editable 安装)
    • 3.7.2 GGUFReader 的核心对象:ReaderField 与 ReaderTensor
    • 3.7.3 读取头部与元数据:fields、contents()、get_field()
    • 3.7.4 遍历张量:名称、形状、类型分布统计
    • 3.7.5 反量化张量:gguf.dequantize() 与 numpy/PyTorch 对接
    • 3.7.6 用 GGUFWriter 写一个最小 GGUF:三步写文件与对齐
    • 3.7.7 原地修改元数据:'r+' 模式与定长标量边界
    • 3.7.8 常见坑:数组字段、变长字段、版本兼容
  • 3.8 type id 兼容性风险:fork/PR 自定义 id 与主线冲突

第二部分 简单块量化

第 4 章 Q4_0:块量化的起点

  • 4.1 18 字节/32 值布局:d: f16 + qs[16]
  • 4.2 公式:(y_i=d(q_i-8)),(q_i\in[0,15])
  • 4.3 block_q4_0 结构体与反量化循环
  • 4.4 量化端:尺度选择与四舍五入夹取
  • 4.5 逐块误差实验:块内分布变化对 Q4_0 的影响
  • 4.6 Q4_0 的局限:单尺度无法适应块内剧烈变化

第 5 章 Q8_0 与简单块家族

  • 5.1 Q8_0:34 字节/32 值,(y_i=d q_i),(q_i\in[-128,127])
  • 5.2 Q4_1/Q5_0/Q5_1/Q8_1 等对称/非对称变体的零点偏移
  • 5.3 Q8_0 作为“近无损基线”的 PPL 与速度
  • 5.4 何时仍应使用简单块量化:极小模型、调试、兼容性
  • 5.5 从 Q4_0 到 K-quants 的动机总结

第三部分 K-quants 核心

第 6 章 K-quants 总览:超级块与两级尺度

  • 6.1 256 值超级块、8 个 32 值子块的基本划分
  • 6.2 通用反量化骨架:(y_i=d\cdot s_j\cdot q_i-d_{\min}\cdot m_j)
  • 6.3 6-bit 尺度/最小值的打包与归一化(除以 63 或 64 的约定)
  • 6.4 为什么层次化尺度能在几乎相同位宽下降低 PPL 劣化
  • 6.5 Q4_K、Q5_K、Q6_K、Q2_K/Q3_K 的家族地图

第 7 章 Q4_K:最常用的 K-quant

  • 7.1 144 字节/256 值布局:d、dmin、scales[12]、qs[128]
  • 7.2 12 字节中 8 个 6-bit 尺度与 8 个 6-bit 最小值的交错打包
  • 7.3 block_q4_K 结构体与 6-bit 解包函数
  • 7.4 反量化循环:子块尺度 (d_j=d s_j/64),偏移 (m_j=d_{\min} m_j/64)
  • 7.5 量化端:子块尺度/最小值的估计与 4-bit 码选择
  • 7.6 逐字节布局图 + Python 参考解码器 + llama.cpp 代码走读
  • 7.7 实验:Q4_0 vs Q4_K 在相同 bit/weight 下的误差与 PPL

第 8 章 Q5_K:4-bit 主体加高位平面

  • 8.1 5-bit 的组成:4-bit qs + 1-bit qh 高位平面
  • 8.2 布局与 block_q5_K 结构体
  • 8.3 反量化:先合并 5-bit 码,再套用 K-quants 子块公式
  • 8.4 质量/体积权衡:Q5_K_M 的 PPL 与速度
  • 8.5 代码走读与高位平面解包陷阱

第 9 章 Q6_K:6-bit 子块与输出层

  • 9.1 16 个 16 值子块、ql[128] 低 4 bit + qh[64] 高 2 bit
  • 9.2 8-bit 有符号子块尺度 scales[16]
  • 9.3 公式:(y_i=d\cdot \mathrm{scales}[j]\cdot(q_i-32))
  • 9.4 为什么输出嵌入层常用 Q6_K
  • 9.5 代码走读与质量实验

第 10 章 Q2_K 与 Q3_K:极端压缩的边界

  • 10.1 Q2_K:16 个 16 值子组、2-bit 主体、低/高半字节存尺度与最小值系数
  • 10.2 非对称公式:(y=d\cdot d_l\cdot q-d_{\min}\cdot d_h)
  • 10.3 Q3_K 的 3-bit 组织与打包要点
  • 10.4 极端压缩下的 PPL 劣化、任务退化与适用边界
  • 10.5 为什么常规部署不推荐 Q2_K 作为默认

第四部分 IQ 系列与码本量化

第 11 章 IQ 系列:重要性矩阵与码本量化

  • 11.1 范式切换:从“尺度 + 最小值偏移”到“重要性加权 + 非线性码本”
  • 11.2 核心思想:imatrix 与加权最小二乘
    • 11.2.1 重要性矩阵的来源:校准数据上的激活统计
    • 11.2.2 加权目标:(\min \sum_i \alpha_i (x_i-\hat{x}_i)^2)
    • 11.2.3 有效位宽谱系:IQ1_S ≈1.5 bpw、IQ2_XXS 2.0625 bpw、IQ3_XXS ≈3.4375 bpw
  • 11.3 码本反量化:lookup table 取代算术尺度
    • 11.3.1 IQ1_S 的 2048 项查找表 iq1s_grid:每项编码 8 个值
    • 11.3.2 尺度与 delta 组合:(y=d\cdot(2k+1)\cdot(\text{grid}[j]\pm\Delta))
    • 11.3.3 IQ2_XXS/IQ3_XXS 的码本容量差异:XXS/XS/S 的索引位分配
  • 11.4 字节布局与代码路径
    • 11.4.1 block_iq1_s 结构:d、qs、qh
    • 11.4.2 dequantize_row_iq1_s 的查表循环 vs K-quants 算术循环
    • 11.4.3 vec_dot 中的 imatrix 索引:imatrix + row*n_per_row
  • 11.5 质量与代价
    • 11.5.1 IQ2_XXS 在 2.06 bpw 下优于 Q2_K
    • 11.5.2 IQ3_XXS 在约 3.4 bpw 下优于 Q3_K
    • 11.5.3 必须提供 imatrix;查表在 SIMD 上的实现难点
  • 11.6 IQ4_NL 与其他 IQ 变体速览
  • 11.7 实验:IQ vs K-quants 在相同 bpw 下的 PPL/KL/速度

第 12 章 UD_IQ:Unsloth Dynamic 的模型级混合

  • 12.1 UD 不是新编码:按层/按张量动态选择标准 GGML 类型的封装
  • 12.2 UD-IQ1_S:底层 IQ1_S + 混合策略,89% 体积缩减下保留约 72% top-1
  • 12.3 与 _M 后缀的区别:内置固定规则 vs 外部敏感度搜索
  • 12.4 UD 的生成流程:敏感度矩阵、逐张量分配、验证
  • 12.5 逐张量类型检查:确认 UD 模型内部的实际类型分布
  • 12.6 质量/体积/速度的三方实验
  • 12.7 生态风险:UD 依赖外部工具版本,跨工具可复现性

第五部分 三值极限量化

第 13 章 三值量化:STQ1_0 与 PTQ1_0

  • 13.1 三值量化的目标:权重压到 ({-d,0,+d}),核心问题是“零的位置如何编码”
  • 13.2 STQ1_0:3:4 稀疏三值
    • 13.2.1 每 4 个权重一组,恰好 1 个零 + 3 个 (\pm d),每组 32 种模式
    • 13.2.2 5-bit 模式编码;块 256 权重 = 64 组
    • 13.2.3 42 字节/块 = 1.3125 bpw(40 字节模式 + 2 字节 FP16 尺度 d)
    • 13.2.4 反量化:(y_i=d\cdot t_i),(t_i\in{-1,0,+1}),零位置由模式隐含
    • 13.2.5 与纯三值 (\log_2 3\approx1.585) bpw 的对比:3:4 约束反而压到 1.31 bpw
    • 13.2.6 llama.cpp 集成:GGML type 43、ARM NEON/AVX2 vec_dot、Metal 后端不完整
  • 13.3 PTQ1_0:稠密三值 + base-3 编码
    • 13.3.1 稠密三值:每个权重独立取 ({-1,0,+1}),不强制稀疏位置
    • 13.3.2 组大小 128、块 28 字节(FP16 尺度 + base-3 trits,每字节 5 个)
    • 13.3.3 实际位宽约 1.75 bpw(含尺度开销)
    • 13.3.4 编码来自 TQ1_0 的 base-3 方案:(y=d\cdot\text{trit}_i)
    • 13.3.5 Hadamard 折叠权重:推理需应用激活侧变换 (y=W'\cdot(H(s\cdot P x)))
    • 13.3.6 工程区别:格式正确但缺失旋转,结果仍然是错的
  • 13.4 STQ1 vs PTQ1_0:设计取舍对照表
    • 三值约束、组大小、实际位宽、编码、运行时依赖、生态成熟度
  • 13.5 质量边界与适用场景
    • 13.5.1 STQ1_0 在 Hy4 上的混合配置平均约 2.38 bpw
    • 13.5.2 三值格式的 PPL 劣化非线性:极低位宽下的阈值效应
    • 13.5.3 不建议作为通用默认;价值在“特定模型 + 特定后端 + 可接受质量边界”
  • 13.6 type id 与 fork/PR 依赖:PTQ1_0 的 143、STQ1_0 的 43
  • 13.7 实验:三值格式 vs IQ1/IQ2 的质量、速度、后端覆盖

第六部分 混合精度与工具链

第 14 章 _S/_M/_L 与逐张量混合精度

  • 14.1 张量敏感度:嵌入、注意力 QKV、FFN gate/up/down、输出层、归一化
  • 14.2 典型 Q4_K_M 的类型分布:Q4_K + Q6_K + F32
  • 14.3 混合精度策略如何生成:规则、重要性矩阵、搜索
  • 14.4 UD 与 _M 的策略对照
  • 14.5 实验:不同 _M/UD 配置的 PPL、KL、体积、速度
  • 14.6 文件内逐张量类型检查脚本

第 15 章 量化工具链与工作流

  • 15.1 convert_hf_to_gguf、llama-quantize、重要性矩阵校准
  • 15.2 校准数据选择与 imatrix 的作用
  • 15.3 完整命令流水线:转换 → imatrix → 量化 → 验证 → 部署
  • 15.4 IQ/UD/三值格式的工具链差异与分支依赖
  • 15.5 版本兼容、对齐、端序与常见失败模式
  • 15.6 可复现实验脚本与目录结构

第七部分 实现与性能

第 16 章 llama.cpp 量化代码架构

  • 16.1 ggml-quants.c、ggml-common.h 与类型分派
  • 16.2 quantize_row_* / dequantize_row_* 的契约
  • 16.3 vec_dot_*:量化点积如何避免完整反量化
  • 16.4 IQ 系列的查表路径与 imatrix 参数传递
  • 16.5 三值格式的模式解码与 SIMD 内核
  • 16.6 CPU SIMD 与 GPU 内核的入口
  • 16.7 如何新增一个 GGUF 量化格式:结构体、注册、测试清单

第 17 章 反量化与矩阵乘性能

  • 17.1 内存带宽瓶颈与 roofline 分析
  • 17.2 尺度解包开销:Q4_0 vs Q4_K vs IQ1_S 的真实速度差异
  • 17.3 SIMD 向量化加载与寄存器布局
  • 17.4 GPU 上 dequant + matmul 的融合策略
  • 17.5 三值格式在后端覆盖不全时的回退路径
  • 17.6 基准方法:tok/s、首 token 延迟、显存占用、批次扩展

第 18 章 正确性验证与质量评估

  • 18.1 逐块单元测试:最大误差、相对误差、边界值
  • 18.2 全模型 PPL、KL 散度、任务评测、长上下文测试
  • 18.3 量化前后 logits 对比与敏感层定位
  • 18.4 三值格式的 Hadamard 变换正确性验证
  • 18.5 可复现实验框架与结果表格模板
  • 18.6 跨实现一致性测试:Python 解码器 vs llama.cpp

第八部分 生态与演进

第 19 章 跨引擎与格式互操作

  • 19.1 用 Python/Rust/JS 实现 GGUF 读取器
  • 19.2 gguf-py 与自研解析器的边界
  • 19.3 与 safetensors/PyTorch 的转换路径
  • 19.4 版本演进、字段兼容与回归测试
  • 19.5 字节布局文档化:如何避免“自定义打包”不兼容
  • 19.6 IQ 码本、三值模式表、Hadamard 元数据的跨实现约定
  • 19.7 互操作测试矩阵

第 20 章 未来与标准化

  • 20.1 更低比特的硬件友好布局
  • 20.2 量化与 KV cache、批处理、长上下文的交互
  • 20.3 格式标准化与生态分裂风险
  • 20.4 type id 治理:自定义 id 与主线合并的冲突
  • 20.5 给实现者的设计建议清单
  • 20.6 全书总结:从 (y=d(q-8)) 到 (y=d s_j q-d_{\min}m_j),再到码本与三值

附录

  • 附录 A 公式速查:Q4_0、Q8_0、Q4_K、Q5_K、Q6_K、Q2_K、Q3_K、IQ1_S、IQ2_XXS、IQ3_XXS、STQ1_0、PTQ1_0 的量化/反量化公式
  • 附录 B 字节布局图集:每个格式的逐字节图与结构体对照,含 IQ 码本与三值模式表
  • 附录 C 最小 Python 参考实现:GGUF 解析、Q4_0/Q4_K/Q6_K/IQ1_S/STQ1_0 解码器
  • 附录 D gguf-py API 速查:GGUFReader、GGUFWriter、dequantize、GGUFValueType、GGMLQuantizationType
  • 附录 E llama.cpp 关键函数索引:按格式列出 quantize/dequantize/vec_dot 入口
  • 附录 F 实验脚本与命令:转换、imatrix、量化、PPL/KL、速度基准
  • 附录 G 术语表:block、super-block、scale、min、imatrix、码本、grid、trit、Hadamard 折叠、PPL、KL 等
  • 附录 H 参考文献与版本说明:论文(QuIP#、Sherry、Prism Hadamard)、llama.cpp PR、格式规范、锁定版本

建议的写作优先级

第一优先(最小闭环):第 3 章(含 3.7 gguf-py)、第 4 章、第 7 章、第 9 章、第 11 章、第 13 章、第 14 章、第 16 章。

第二优先(格式变体与工具链):第 5、8、10、12、15 章。

第三优先(性能、验证、生态):第 17–20 章与附录。

posted @ 2026-10-27 13:49  绝不原创的飞龙  阅读(77)  评论(0)    收藏  举报