llama.cpp Q 量化方式总结

llama.cpp Q 量化方式总结

TheBloke 里有许多不同量化方式的模型,如下:

1
2
3
4
5
6
7
8
9
CapybaraHermes-2.5-Mistral-7B-GGUF
| - capybarahemers-2.5-mistral-7b.Q2_K.gguf
| - capybarahemers-2.5-mistral-7b.Q3_K_L.gguf
| - capybarahemers-2.5-mistral-7b.Q3_K_M.gguf
| - capybarahemers-2.5-mistral-7b.Q3_K_S.gguf
| - capybarahemers-2.5-mistral-7b.Q4_0.gguf
| - capybarahemers-2.5-mistral-7b.Q4_K_M.gguf
| - capybarahemers-2.5-mistral-7b.Q4_K_S.gguf
| ...

它们都属于 llama.cpp 中 Q 量化定义的范围。llama.cpp 里的 Q 量化有两个格式:QX_YQX_K,第一种是对称量化和非对称量化,第二种是 K 量化 (k quants)。

QX_Y 量化方式

Q4_0 结构体

1
2
3
4
5
#define Q4_0 32
typedef struct {
ggml_half d; // delta
uint8_t qs[Q4_0 / 2]; // nibbles / quants
} block_q4_0;

可以看到每个 block 共有 32 个权重,每个权重占用 4bit,每两个权重共享一个 uint8_t。同时,整个 block 共享一个相同的缩放系数。

含义

QX_Y 量化方式里 XY 均为数字,常用的有 Q4_0Q4_1。其含义如下:

  • X: 量化 bit 数,如 345 等。
  • Y: 反量化方式
    • Y 为奇数时,量化为非对称量化,反量化方式为 $x=d \times q + m$ ,其中 $d$ 为 scale、 $q$ 为 quant-value、 $m$ 为 block-minimal;Y 为偶数时,量化为对称量化,反量化方式为 $x = d \times q$ 。
    • Y/2 代表了 block size 的大小,当 Y 为 0/1 时,block size 为 32;当 Y 为 2/3 时,block size 为 16。

QX_K 量化方式

随着 block size 增大,共享缩放系数的权重数量减小,可以预见模型的性能(以 perplexity 衡量)可以增加。但是 block size 的增加会导致缩放系数的数量增加,导致 block 整体的存储开销增大。llama.cpp 中以 bits per weight (bpw) 衡量,此时不如使用更高 bit 数的量化方式。

K 量化的原理是:我们可以将多个 scale 放在同一个数组中,然后对这个 scale 数组进行量化,得到一个 scale 数组的 scale,这样就可以减少 block 的存储开销。因此需要合并多个 Q4_0 block 到一起,减小整体的存储开销。

Q4_K 结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define K_SCALE_SIZE 12
#define QK_K 256

typedef struct {
union {
struct {
ggml_half d; // super-block scale for quantized scales
ggml_half dmin; // super-block scale for quantized mins
} GGML_COMMON_AGGR;
ggml_half2 dm;
}

uint8_t scales[K_SCALE_SIZE]; // scales and mins, quantized with 6 bits
uint8_t qs[QK_K / 2]; // 4-bit quants
} block_q4_K;

block_q4_K 结构体中有 256 个权重,该 super block 拥有 256/32=8 个 block,每个 block 的 scale 和 min 被量化成了 6bit,并以数组形式保存在 scales 中。

block_q4_0 的 bpw: $(16 + 32 \times 4) / 32 = 4.5$ ;block_q4_K 的 bpw: $(2 \times 16 + 12 \times 8 + 256 \times 4) / 256 = 4.5$ 。二者的 bpw 相同,但是 block_q4_K 存储了更多 scale 和 min,直观上来说,其困惑度会更低。

参考链接

  1. k-quants 的介绍,以 K 结尾的量化
  2. QX_4 量化
  3. 混合比特量化

llama.cpp Q 量化方式总结
http://hebangwen.github.io/2024/10/29/llamacpp-q-quants/
作者
何榜文
发布于
2024年10月29日
许可协议