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,直观上来说,其困惑度会更低。