llama.cpp Q 量化方式总结
llama.cpp Q 量化方式总结
TheBloke 里有许多不同量化方式的模型,如下:
1 |
|
它们都属于 llama.cpp 中 Q 量化定义的范围。llama.cpp 里的 Q 量化有两个格式:QX_Y
和 QX_K
,第一种是对称量化和非对称量化,第二种是 K 量化 (k quants)。
QX_Y
量化方式
Q4_0
结构体
1 |
|
可以看到每个 block 共有 32 个权重,每个权重占用 4bit,每两个权重共享一个 uint8_t
。同时,整个 block 共享一个相同的缩放系数。
含义
QX_Y
量化方式里 X
和 Y
均为数字,常用的有 Q4_0
和 Q4_1
。其含义如下:
X
: 量化 bit 数,如3
、4
、5
等。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 |
|
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,直观上来说,其困惑度会更低。