低比特数值格式#
本页内容7 个部分
在学习量化算法之前,先要回答一个更基础的问题:低 bit 到底如何表示数字?
4 bit 最原始的含义只有:
也就是说,一个 4-bit code 只有 16 种状态。但 4 bit 并没有规定这 16 个状态分别代表哪些真实数值。INT4、FP4、NF4 之所以不同,本质上是因为它们用不同方式把有限的 bit pattern 映射到数轴。
这篇笔记只讨论 low-bit number representation 本身,不进入具体量化算法。
1. Bit-width:码点是一种预算#
bit 一共提供:
例如 4 bit:
0000
0001
0010
...
1110
1111
一共只有 16 种 pattern。我们可以让它们表示均匀整数,也可以表示浮点数,甚至可以直接查一张任意的 16-entry codebook。
因此第一条基本原则是:
低 bit 表示的核心问题其实是:
有限的 reconstruction levels 应该放在数轴的哪些位置?
可以把每一个 reconstruction level 看成一份表示能力预算。4 bit 只有 16 份预算,把更多码点放在某个数值区域,就意味着其他区域必须更稀疏,或者干脆无法覆盖。
2. Integer:均匀网格#
最直接的方法是让 code 对应等间距整数。
例如 signed INT4 的 two's-complement 编码可以表示:
数轴上的相邻整数间距固定:
-8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
| | | | | | | | | | | | | | | |
因此 integer family 的核心几何特征是:
2.1 Signed 与 Unsigned#
如果数据同时包含正负值,可以使用 signed integer;如果数据天然非负,则可以把全部码点放在正半轴。
例如 UINT4:
0 1 2 3 4 5 ... 13 14 15
| | | | | | | | |
同样是 4 bit,signed / unsigned 的区别本质上也是:把 16 个码点预算分配到数轴的什么位置。
2.2 Code 不等于真实 reconstruction value#
在神经网络量化里,INT4 code 通常还会配合 scale。假设使用对称整数范围:
真实重建值可以写成:
所以需要区分:
- :低 bit code;
- :反量化后真正参与数值计算的 reconstruction value。
如果为了严格正负对称而使用 ,那么 two's-complement INT4 中的 -8 pattern 不被量化器使用,实际只有 15 个有效 reconstruction levels。这也说明:物理上有 16 个 bit pattern,不代表某个具体 quantizer 一定会使用全部 16 个。
3. Floating Point:用 exponent 换动态范围#
Floating point 不再追求数轴上的等间距,而是把 bits 拆成:
忽略特殊值和编码细节,可以粗略理解成:
其中:
- sign 决定正负;
- exponent 决定数量级,因此主要控制 dynamic range;
- mantissa 决定同一数量级内部能分多细,因此主要控制 local precision。
所以:
3.1 常见格式#
| 格式 | Sign | Exponent | Mantissa | 直觉 |
|---|---|---|---|---|
| FP16 | 1 | 5 | 10 | 标准半精度 |
| BF16 | 1 | 8 | 7 | 保留接近 FP32 的 exponent range |
| FP8 E4M3 | 1 | 4 | 3 | 更偏 precision |
| FP8 E5M2 | 1 | 5 | 2 | 更偏 range |
| FP4 E2M1 | 1 | 2 | 1 | 极低 bit 浮点 |
E4M3 与 E5M2 很能体现浮点设计的 trade-off:二者都是 8 bit,但 E5M2 多给 exponent 一位,因此覆盖范围更大;E4M3 多给 mantissa 一位,因此局部表示更细。
3.2 FP 的网格为什么不均匀#
Integer 更像:
|--|--|--|--|--|--|--|--|
Floating point 更像:
| | | | | | | | |
随着 magnitude 增大,相邻 representable values 的绝对间距也会增大。因此 floating point 更接近保持 relative precision,而 uniform integer 更接近保持固定的 absolute spacing。
这也意味着 FP 并不天然比 INT 更适合低 bit。总状态数固定时,FP 必须拿出一部分编码能力表示 exponent。如果数据本身动态范围并不大,而主要集中在一个有限区间,那么为远端数量级预留的表示能力可能并不划算。
低 bit 下没有天然“更高级”的格式,只有 reconstruction grid 是否匹配数据分布。
4. Codebook / Non-uniform Formats:直接设计 reconstruction levels#
既然 4 bit 只有 16 个 code,那么并不一定需要通过整数公式或 exponent/mantissa 来解释它们。最自由的方法是直接定义:
例如:
0000 → -1.00
0001 → -0.70
0010 → -0.52
0011 → -0.39
...
1110 → +0.72
1111 → +1.00
这就是 codebook quantization。16 个 reconstruction points 可以完全不等间距,因此可以根据数据分布把更多码点放到高概率区域。
4.1 NF4#
上面的 LUT 只是示意值,不是 NF4 的实际 codebook。NF4 的码点按正态分位数构造并包含精确的零;它不是对任意权重分布、任意误差指标都最优。
NF4(NormalFloat 4-bit)可以从这个视角理解:它不是简单缩小版的 IEEE floating point,而是一种面向近似 normal / bell-shaped neural-network weight distribution 的非均匀 4-bit representation。
Uniform grid:
|----|----|----|----|----|----|
Distribution-aware non-uniform grid 的直觉则是:
|------|---|-|-|-|-|---|------|
↑
中心更密
如果数据大量集中在中心区域,就可以把更多 reconstruction levels 分配在那里,提高有限 bit budget 的利用率。
4.2 自由度与 decode 成本#
Codebook 的优势是 reconstruction levels 几乎可以任意设计;代价是 decode 往往需要 data-dependent lookup:
相比之下,uniform integer 一类格式可能只需要简单 arithmetic。于是低 bit format 的设计不只是数值误差问题,还天然包含一个工程 trade-off:
5. Block Scaling / Microscaling:把动态范围交给共享 metadata#
单个 4-bit value 的表示能力非常有限。如果要求每个 value 独自同时承担很大的 dynamic range 和很高的 local precision,通常很困难。
现代低 bit 表示常用的办法是:把数据分成小 block,让多个低 bit values 共享额外的 scale。
Block 0
┌──────────────────────────┐
│ shared scale = s₀ │
│ 4b 4b 4b 4b ... │
└──────────────────────────┘
Block 1
┌──────────────────────────┐
│ shared scale = s₁ │
│ 4b 4b 4b 4b ... │
└──────────────────────────┘
概念上:
其中:
- 是低 bit element code;
- 是 element format 的 reconstruction rule;
- 是整个 block 共享的 scale。
可以把两者理解成:
这样 element format 不再需要独自覆盖整个 tensor 的数量级变化。
5.1 MX / Microscaling#
MX family 可以从这个框架理解为:
MXFP4 常用 32 个 E2M1 元素共享一个 E8M0 scale;NVFP4 则采用 16 个 E2M1 元素共享 E4M3 scale,并另有 tensor scale。因此 FP4 与 MXFP4 不是同一层概念:前者描述单个 element 如何编码,后者进一步规定一组 elements 如何共同表示数值。
5.2 NVFP4#
NVFP4 同样属于 block-scaled FP4 的思路。可以用三级结构建立直觉:
Tensor
│
├── tensor / global scale
│
├── Block 0
│ ├── FP8 E4M3 block scale
│ └── 16 × FP4 E2M1 values
│
├── Block 1
│ ├── FP8 E4M3 block scale
│ └── 16 × FP4 E2M1 values
│
└── ...
概念上:
这里不同层次负责不同问题:
- FP4 E2M1:描述 block 内部的低 bit local value;
- FP8 E4M3 block scale:让小 block 适配自己的局部 magnitude;
- tensor/global scale:承担更高层次的整体动态范围。
NVFP4 使用较细的 block(16 elements),其基本 trade-off 是:
这也是 block scaling 的一般规律。
6. 统一视角:Code + Reconstruction + Metadata#
到这里,各种低 bit representation 可以放进同一个框架:
| Representation | Code Space | Reconstruction Rule | Shared Metadata |
|---|---|---|---|
| INT4 | 4-bit integer | uniform integer grid | 无或外部 scale |
| FP4 E2M1 | 4-bit FP code | sign/exponent/mantissa decode | 无 |
| NF4 | 4-bit index | non-uniform codebook / LUT | 常与 block scale 配合 |
| MXFP4 | FP4 element | FP4 decode × block scale | shared block scale |
| NVFP4 | FP4 E2M1 element | FP4 × local scale × higher-level scale | FP8 block scale + tensor/global scale |
这张表最重要的不是记格式名字,而是形成三个问题:
- 有多少 code? —— bit-width 决定状态预算。
- 每个 code 在数轴上对应哪里? —— reconstruction rule 决定 grid geometry。
- 一组 values 还能共享什么信息? —— metadata 帮助低 bit element 获得额外 dynamic range / local adaptation。
最后还要严格区分:
INT4、FP4 E2M1 主要是在描述 number format / code space;而一个完整的神经网络 quantization scheme 往往还需要进一步指定 scale、zero-point、granularity、calibration、clipping,以及最终的硬件 decode 路径。
因此学习顺序最好是:
low-bit number formats
↓
quantization mapping / scale / zero-point / granularity
↓
quantization algorithms
↓
hardware-aware deployment
先理解“这些 bits 如何表示数字”,后面的量化方法才有统一的坐标系。
参考资料#
QLoRA:NF4 的定义、NVIDIA:NVFP4 与 MXFP4 的格式比较。格式的特殊值、scale 编码与支持的算子应以具体实现为准。