把三件衣服分别塞进四个抽屉,总会空出一个。三进制模型也有类似浪费:它的权重只取负、零、正三种状态,通用二进制格式却没有完全贴合这三个选项。开发者 pmttyji 提出的 Q2_B3,又称“B3S”,就是为这类权重定做的 GGUF 打包方式。它声称能把权重占用压低约 22%,让显存有限的设备更容易装下模型。
这里的数字和效果均来自作者在 Reddit 的自述。目前没有论文、代码仓库链接、第三方测试或复现实验可供交叉验证,因此更适合把它看作一个值得验证的工程方案,而非已经坐实的性能结论。
三个状态,就按三进制装
三进制模型把每个权重限制为 三种状态。BitNet-b1.58 和 Ternary-Bonsai 是作者列举的例子。“1.58-bit”来自 :三个等可能状态的理论信息量约为 1.58 bit,但这不代表实际文件一定能做到每个权重恰好占 1.58 bit。
B3S 的思路很直接:既然只有三个状态,就用 base-3 packing(三进制打包)直接编码,不再给不存在的第四种状态留位置。每个 block——一组共同存储和处理的权重——包含 128 个权重,用 26 bytes 保存三进制数位,再配一个 f16 scale。scale 是把这些离散状态还原到实际数值尺度所需的缩放系数,f16 表示它用 16 位浮点数保存。合计是 28 bytes/block,即每个权重实际占 1.75 bit。
作者估算,9B 模型的权重可由 Q2_0 的约 2.5 GB 降至 B3S 的约 2.0 GB;27B 则由约 7.6 GB 降至约 5.9 GB。前一个例子约省 20%,后一个约省 22.4%,所以“约 22%”并不是所有模型都能直接套用的固定比例。
“无损”只限打包这一步
这里最容易误解的是 lossless。B3S 不是把普通 FP16 模型无损压到 1.75 bit,也不是通用的 2-bit quantizer——量化器会用更少的数值表示原始权重。作者明确警告:若直接输入普通 FP16 模型,质量会严重下降。
它只适用于权重本来就已经是三进制的模型。在这个前提下,B3S 仍保存同样的 状态和 f16 block scale,因此编码本身不再丢掉一层精度。但这不等于模型相对 FP16/BF16 无损,也不能推出推理输出逐位一致。
省下的是权重,不是全部显存
GGUF 是本地大模型常用的权重文件格式。新增一种类型,不只要能写进文件,还需要推理引擎和不同硬件后端读懂它。作者的实现基于 llama.cpp commit 4e97ac86e 的 fork,加入 Q2_B3 类型及相关 backend 支持。
主要运行路径是 AMD ROCm/HIP,开发和调优使用 RDNA3/gfx1100 架构的 Radeon RX 7900 XTX。CPU 后端可以运行;NVIDIA CUDA 和 Apple Metal 目前只确认能够编译,因为作者没有相应硬件,尚未真机验证。
此外,约 22% 指的是权重体积。长对话还要占用 KV 缓存——模型保存已处理上下文中间结果的“草稿纸”——以及运行时缓冲区。作者估计 context/KV 可能另需约 1–2 GB,但实际数字会随上下文长度、批量和 KV 精度变化。因此,权重缩小 22%不等于整套推理显存也同比减少。
为什么值得关注
三进制模型的卖点之一,是用极少的状态表示权重;如果落到本地文件时仍沿用不够贴合的通用布局,理论上的紧凑性就会被格式开销吃掉一部分。B3S 补的正是这一层:它没有提出新的模型训练方法,而是试图让现有三进制权重在 GGUF 和 llama.cpp 体系里存得更像三进制。
作者还提供了 repacker,可把旧版 30-byte、双 scale 的 Q2_B3 GGUF 转换为当前 28-byte、单 scale 的 B3S 布局,并称转换前会检查每个 block。不过供稿在校验条件处被截断,不能据此认定所有旧文件都能安全转换。
局限与未知
- 目前只有作者单一信源,约 22% 的降幅缺少统一口径说明和第三方复现。
- 作者尚未给出速度或 perplexity(衡量模型预测文本能力的常用指标)表格,只称自己的硬件测试未见明显 PPS 或解码速度损失;测试配置和具体数据均未披露。
- CUDA、Metal 尚未经对应硬件验证,完整运行显存和模型质量也不能仅由权重文件大小推断。