数值类型
数值类型定义一组 bit 如何解释成数值。按照量化知识树,本文只分为两类:保留指数与尾数结构的 Float,以及使用离散整数编码的 Integer。
位宽(bit width)只表示一个元素占用多少 bit。
| 概念 | 回答的问题 | 示例 |
|---|---|---|
| 位宽 | 一个元素使用多少 bit | 4 bit、8 bit、16 bit |
| 数值类型 | 这些 bit 如何解释 | INT8、FP8 E4M3、BF16 |
| 数值映射 | 原始数值如何缩放到目标编码 | scale、zero-point、对称或非对称映射 |
| 完整量化配置 | 哪些对象采用什么格式和粒度 | W4A16、W8A8、NVFP4 |
因此,数值类型是量化方案的一部分,不能单独决定 WxAy、scale 粒度或 Kernel 路径。
Float
Float 将 bit 分给符号、指数和尾数。对规范化二进制浮点数,可以将其结构概括为:
其中,符号位
| 格式 | 总位宽 | 指数位 | 尾数位 | 主要特点 |
|---|---|---|---|---|
| FP16 | 16 | 5 | 10 | 尾数较多,精度高于同位宽的 BF16,但动态范围更小 |
| BF16 | 16 | 8 | 7 | 指数宽度与 FP32 相同,适合承载大模型的常规计算 |
| FP8 E4M3 | 8 | 4 | 3 | 在两种常见 FP8 中偏向保留有效精度 |
| FP8 E5M2 | 8 | 5 | 2 | 在两种常见 FP8 中偏向扩大动态范围 |
| FP4 E2M1 | 4 | 2 | 1 | 局部状态很少,通常需要更细粒度的 scale |
ExMy 中的 E 表示 Exponent,M 表示 Mantissa;加上 1 个符号位,总位宽为
FP16 / BF16
FP16 和 BF16 都是 16-bit Float,通常作为大模型推理的高精度基线、Activation dtype 或低精度 GEMM 的输出格式。
- FP16:使用 5 位指数和 10 位尾数,保留更多有效数字。
- BF16:使用 8 位指数和 7 位尾数,动态范围接近 FP32,更不容易因数值过大而溢出。
同为 A16,具体实现可能使用 FP16,也可能使用 BF16,因此 W4A16 仍需结合模型 dtype 和 Kernel 接口理解。
FP8(E4M3 / E5M2)
FP8 主要包含 E4M3 与 E5M2 两种元素格式。E4M3 用更多尾数位换取精度,E5M2 用更多指数位换取动态范围;具体格式还会规定特殊值、最大有限值和舍入行为。
“FP8”只说明元素如何编码,不等于一种完整的 W8A8 方案。Fine-Grained FP8、MXFP8 和普通 per-tensor FP8 都可以使用 FP8 元素,但它们的 scale 类型、共享粒度和 Kernel 布局不同。
FP4(E2M1)
FP4 E2M1 只使用 1 个符号位、2 个指数位和 1 个尾数位,单个元素只能表示很少的局部状态。为了控制误差,实际方案通常让较小 block 共享 scale。
NVFP4 会使用 FP4 E2M1 元素,但 NVFP4 不是 FP4 的同义词:它还规定局部 scale、全局 scale 和 block size,并且既可以组成 W4A4,也可以用于 W4A16 Weight-Only 路径。具体组合见量化配置。
Integer
Integer 使用离散整数编码。下表中的有符号范围按二进制补码列出;实际量化方案也可以为了正负对称而舍弃一个端点,例如用 [-127,127] 代替完整 INT8 范围。
| 格式 | 位宽或理论信息量 | 代表性状态 | 编码数量 | 常见定位 |
|---|---|---|---|---|
| INT8 | 8 bit | 256 | W8A8 Weight-Activation | |
| INT4 | 4 bit | 16 | W4A16 Weight-Only,也可用于更低精度 Activation | |
| INT2 | 2 bit | 4 | 极低比特 Weight | |
| Ternary(W1.58) | 3 | 三值 Weight | ||
| INT1 | 1 bit | 两种离散状态 | 2 | Binary Weight |
整数编码本身不包含原始浮点范围。如何使用 scale 和 zero-point 将浮点值映射到整数,属于独立的数值映射层;这里只讨论目标元素能够保存哪些离散状态。
INT8
INT8 包含 256 种编码,是常见的 Weight-Activation 整数量化格式。W8A8 可以让 Weight 和 Activation 都使用 INT8,但两侧仍可采用不同粒度,例如 per-output-channel Weight 与 per-token Activation。
LLM.int8() 会让大部分矩阵乘进入 INT8 路径,同时将 outlier 维度保留在 FP16;SmoothQuant 则通过等价变换降低 Activation 的量化难度。
INT4
INT4 包含 16 种编码,典型用途是 W4A16 Weight-Only。Weight 常以 packed INT4 保存,Kernel 读取后解包并结合 scale 计算;GPTQ 和 AWQ 都可以生成这类低比特 Weight。
INT4 也可以参与 W4A8 或 W4A4,但位宽名称本身不能说明 Activation 格式、量化粒度和硬件是否提供对应 Kernel。
INT2
INT2 只有 4 种编码。状态数量进一步减少后,量化误差更难控制,通常需要更细的分组、更强的误差补偿或模型级混合精度;实际收益还取决于后端是否支持高效的 2-bit 打包与计算。
Ternary(W1.58)
Ternary Weight 使用
因此 W1.58 表示理论信息量,不是硬件原生提供的“1.58-bit dtype”。实际存储占用由编码、打包、对齐和相关元数据决定。本文按照知识树将它归入 Integer 分支,本质上它是离散三值 Weight 格式。
INT1
1 bit 只能区分两种状态。Binary Weight 可以选择
无论使用 Float 还是 Integer,较低位宽只有在 checkpoint 布局、scale 元数据、打包方式和 Kernel 都匹配时,才能转化为实际的容量、带宽或计算收益。
参考
- IEEE 754-2019:IEEE Standard for Floating-Point Arithmetic
- NVIDIA TensorRT:Quantized Types and Schemes
- Hugging Face Transformers:Quantization Concepts
- LLM.int8():8-bit Matrix Multiplication for Transformers at Scale
- GPTQ:Accurate Post-Training Quantization for Generative Pre-trained Transformers
- AWQ:Activation-aware Weight Quantization for LLM Compression and Acceleration
- NVIDIA Transformer Engine:FP8 and FP4 Primer
- BitNet b1.58:The Era of 1-bit LLMs