1. 数学原理
对于任意浮点型向量 $\boldsymbol{x}$,为了把浮点数压缩到整数格子上,并且尽量少丢失精度,其 INT8 存储的整型向量 $\tilde{\boldsymbol{x}}$ 为:
$\tilde{\boldsymbol{x}}=\text{clip}\left[\text{round}\left(\dfrac{\boldsymbol{x}}{\Delta(\boldsymbol{x})}\right),-127,+127\right]$
反量化后的浮点型向量 $\hat{\boldsymbol{x}}$ 为:
$\hat{\boldsymbol{x}}=\tilde{\boldsymbol{x}}\Delta(\boldsymbol{x})$
其中格子的宽度(尺度)即:
$\Delta(\boldsymbol{x})=\dfrac{\max|\boldsymbol{x}|}{127}$
需要注意的是,工程设计上整数矩阵乘法用 INT32 累加,不能用 INT8 累加,否则极易溢出.
2. 量化过程
一个浮点数激活层行向量是 $\boldsymbol{x}=[8.0, 1.0]$,浮点型权重是:
$\boldsymbol{W}=\left[\begin{matrix}
0.25 & -0.50 \\
0.10 & 0.20 \\
\end{matrix}\right]$
则通过 GEMM 后正确的输出是:
$\boldsymbol{y}=\boldsymbol{x}\boldsymbol{W}=[8.0, 1.0]\left[\begin{matrix}
0.25 & -0.50 \\
0.10 & 0.20 \\
\end{matrix}\right]=[2.10, -3.80]$
不同的量化方法都是设计一套低耗时的运算,并且尽可能接近这个 $\boldsymbol{y}=[2.10,-3.80]$ 答案.
INT8 我们假定取值范围是 -127~127 上的整数,对于向量 $\boldsymbol{x}$ 而言,用绝对最大值作为铺满格子的尺度,那么有:
$\Delta(\boldsymbol{x})=\dfrac{8.0}{127}\approx0.062992$
因此有如下量化映射关系:
$\begin{align*}
8.0\to127.0\to\text{clip}\left[\text{round}\left(127.0\right),-127,127\right]=127
\\[4pt]
1.0\to15.875\to\text{clip}\left[\text{round}\left(15.875\right),-127,127\right]=16
\end{align*}$
若反量化还原回去,得到:
$\begin{align*}
127\to8.0
\\[4pt]
16\to1.008
\end{align*}$
我们发现 1.008 并没有精确地复原成 1.0,这就是量化误差. 格子越窄,误差通常越小,但倘若格子太窄,绝对值很大的数据会超过 127 而被截断.
根据矩阵乘法运算,我们计算 $\boldsymbol{x}\boldsymbol{W}$ 时候,是向量的行与矩阵的列做点积,因此矩阵的量化我们按照列以同样的思路可以得到:
$\begin{align*}
\Delta([0.25, 0.10]^{\top})&=\dfrac{0.25}{127}\approx0.001969
\\[4pt]
\Delta([-0.50, 0.20]^{\top})&=\dfrac{0.50}{127}\approx0.003937
\end{align*}$
因此有如下量化映射关系:
$\begin{align*}
[0.25,0.10]^{\top}\to[127,51]^{\top}
\\[4pt]
[-0.50,0.20]^{\top}\to[-127,51]^{\top}
\end{align*}$
逆反量化:
$\begin{align*}
[127,51]^{\top}\to[0.25, 0.1]^{\top}
\\[4pt]
[-127,51]^{\top}\to[-0.50,0.201]^{\top}
\end{align*}$
实际上,当量化为 INT8 整数类型后,只需要做整数乘法运算即可:
$\begin{align*}
[127,16]\cdot[127,51]^{\top}=16981
\\[4pt]
[127,16]\cdot[-127,51]^{\top}=-15313
\end{align*}$
然后:
$\begin{align*}
16981\times\Delta(\boldsymbol{x})\times\Delta([0.25, 0.10]^{\top})\approx2.101184
\\[4pt]
-15313\times\Delta(\boldsymbol{x})\times\Delta([-0.50, 0.20]^{\top})\approx-3.797632
\end{align*}$
这就是最普通的 W8A8 反量化结果 $[2.101184,-3.797632]$,它非常靠近正确输出 $[2.10, -3.80]$,推理引擎类似 vLLM 只需要根据量化后的结果和尺度(亦可理解为缩放因子)即可还原精度接近的反量化结果.