|
| 1 | +--- |
| 2 | +title: "SVDQuant" |
| 3 | +date: 2025-12-15 14:58:00 +0800 |
| 4 | +categories: ["quantization", "SVDQuant"] |
| 5 | +tags: [diffusion-models, reading-notes, generative-models] |
| 6 | +math: true |
| 7 | +--- |
| 8 | + |
| 9 | + |
| 10 | +我认真读SVDQuant的代码应该也最少有两次了,想着应该留下一些痕迹。第一次读的时候我还不太搞得懂 `forward` 是怎么一回事,现在再读已经是为了给推理引擎的`feature`做准备了。从还在读大四的实习生大模型小白到开始掌握 ai infra入门的正式员工,都时不时接触这个项目,还挺感慨的。 |
| 11 | + |
| 12 | +## 前置: 什么是量化? |
| 13 | +令人惊讶的是网上居然很少有这方面科普类的文章,比如一文带你读懂什么是模型量化,甚至连 ai 生成的水文也比较少(可能是我搜索的关键词不太对)。总之 Quantization 是一门广泛使用且基础的模型轻量化技术。我不打算写的很详细。 |
| 14 | + |
| 15 | +详细的可以看看["Working with Quantized Types"](https://docs.nvidia.com/deeplearning/tensorrt/latest/inference-library/work-quantized-types.html#) |
| 16 | + |
| 17 | +### RTN量化 |
| 18 | +我觉得最能体现量化核心思想的是RTN量化(Round-To-Nearest): |
| 19 | +1. 找到未量化 `X:Tensor` 的最小值 $X_{min}$ 和最大值 $X_{max}$ |
| 20 | +2. 根据量化精度 $Q$ 计算 scale 和 zero point |
| 21 | + |
| 22 | +对于对称量化(zero point = 0): |
| 23 | + |
| 24 | +$$ |
| 25 | +X_{quantized} = round\left(\frac{X}{scale}\right) |
| 26 | +$$ |
| 27 | + |
| 28 | +$$ |
| 29 | +X_{dequantized} = X_{quantized} \times scale |
| 30 | +$$ |
| 31 | + |
| 32 | +对于非对称量化: |
| 33 | + |
| 34 | +$$ |
| 35 | +X_{quantized} = clamp\left(round\left(\frac{X}{scale} + zero\text{_}point\right), Q_{min}, Q_{max}\right) |
| 36 | +$$ |
| 37 | + |
| 38 | +$$ |
| 39 | +X_{dequantized} = (X_{quantized} - zero\text{_}point) \times scale |
| 40 | +$$ |
| 41 | + |
| 42 | +其中: |
| 43 | +- $scale = \frac{X_{max} - X_{min}}{Q_{max} - Q_{min}}$,`dtype` 与量化前的`X`一致 |
| 44 | +- $\text{zero\_point} = round\left(Q_{min} - \frac{X_{min}}{scale}\right)$ |
| 45 | +- $Q_{min}$ 和 $Q_{max}$ 是量化后的精度范围,如`torch.int8`为[-128,127] |
| 46 | +- $clamp(x, min, max)$ 操作将 $X$ 限制在 $[min, max]$ 范围内 |
| 47 | + |
| 48 | +不难理解为什么量化会得到 `X_q` 和 `scale_X`,因为量化实际上就是将一个高精度范围(推理的精度通常为`torch.bfloat16`)映射到一个低精度范围(`torch.int8`, `torch.fp8`, `torch.int4`...)内,而高精度范围会比低精度范围大,所以需要一个比例来将低精度范围放大,这样才能保证量化前后的数值正确——至少在可容忍的误差范围内。 |
| 49 | + |
| 50 | +对 X 来说,如果我们选择只对权重 W 量化,就是所谓的`weight-only quantization`,如果我们对激活A 和权重 W 都量化,就是所谓的`weight-activation quantization`。例如我们只将权重量化为 4bit,我们就把它叫做`W4A16`,如果权重和激活都量化成 4bit,就叫做`W4A4`。 |
| 51 | + |
| 52 | +对于步骤 1 来说,我们如何选择最值,是选择整个 tensor(per tensor)的最值,还是选择矩阵中每一行的最值(per channel),就是所谓的**量化粒度**,从直觉上来说粒度当然是越细越好。 |
| 53 | + |
| 54 | +对于步骤 2 来说,我们选择的量化精度实际上是需要根据推理运行的硬件来选择的,例如英伟达 4090 显卡支持 fp8 计算,而 3090 `Tensor Core` 不支持fp8, 推理速度可能和 bf16 差不多。 |
| 55 | + |
| 56 | +接下来稍微仔细一点地说明为什么需要在意量化粒度与量化精度,以及为什么一个单纯的模型权重可以被量化激活。 |
| 57 | + |
| 58 | +### 为什么要在意量化粒度 |
0 commit comments