NVFP4(常见 W4A4)
NVFP4 是 NVIDIA 的 FP4 分层缩放方案:数据使用 FP4 E2M1,每 16 个元素共享一个 FP8 E4M3 局部 Scale,整个 Tensor 再共享一个 FP32 全局 Scale。它通过细粒度两级缩放弥补 4-bit Float 表示能力不足,最常用于 Linear 的 W4A4 推理。
原理
E2M1 数据
E2M1 将 4 bit 分为 1 个符号位、2 个指数位和 1 个尾数位,可表示:
E2M1 的格点不等距:小数值附近更密,大数值附近更疏,最大幅值为 6。与 INT4 不同,它保留了浮点数的指数结构,但 15 个不同数值仍不足以直接覆盖模型中变化很大的 Weight 和 Activation,因此必须配合 Scale。
两级缩放
NVFP4 将高精度值近似为:
:E2M1 量化值; :第 个 16-element Block 的 E4M3 局部 Scale; :整个 Tensor 共享的 FP32 全局 Scale。
设 Tensor 和第
两级 Scale 分工明确:
- 全局 Scale:把整个 Tensor 的动态范围映射到 E4M3 Scale 可表示范围;
- 局部 Scale:让每 16 个元素独立适应局部分布,减小异常值对其他 Block 的影响;
- E2M1 数据:在缩放后的局部范围内保存真正参与矩阵乘的 4-bit 值。
部分实现保存的是 encode global scale global_scale 字段名。
W4A4 Linear
对输入
Weight:离线量化 → packed E2M1 + E4M3 block scales + FP32 global scale
Input :运行时量化 → packed E2M1 + E4M3 block scales + FP32 global scale
↓
block-scaled FP4 GEMM
↓
FP32 accumulate → BF16/FP16 outputWeight 通常静态保存在 Checkpoint 中;Activation 随请求变化,因此局部 Scale 通常在运行时按 Token 和 K 维 Block 动态计算。局部 Scale 必须在每个 K Block 的部分和中应用,而不是等完整 GEMM 结束后只乘一次。
对一维 16-element Scaling,Weight
| 数据 | Shape | dtype |
|---|---|---|
| Packed Weight | [N, K / 2] | uint8,每个 Byte 保存两个 E2M1 |
| Block Scales | [N, K / 16] | FP8 E4M3 |
| Global Scale | [1] 或每个逻辑分片一个 | FP32 |
忽略 Padding 和分片元数据,每个元素的理论存储为:
因此 NVFP4 常被简称为 4 bit,但带局部 Scale 的实际渐近成本约为 4.5 bit/element。
Activation 的常见组合
WxAy 中的 A 表示 Linear 输入 Activation 的量化位宽,不表示输出或累加器精度。Activation 值通常不保存在 Checkpoint 中,而是在推理时根据当前输入动态量化。
| 配置 | Weight | Activation | 典型定位 |
|---|---|---|---|
| NVFP4 W4A4 | NVFP4 E2M1 | NVFP4 E2M1,运行时动态计算局部 Scale | 最常见的 NVFP4 组合,两侧都进入 FP4 GEMM |
| NVFP4A16 / W4A16 | NVFP4 E2M1 | BF16 或 FP16,不量化 | Weight-Only,主要减少 Weight 容量与带宽 |
| W4A8 | 4-bit Weight | FP8 或 INT8 | 混合精度;Weight 可能是 NVFP4、MXFP4 或 INT4,必须查看格式元数据 |
因此,NVFP4 支持 A4,但也可以只用于 Weight。NVFP4 Weight 与 A8 的组合依赖特定 Runtime,不属于标准 NVFP4 W4A4 路径。即使输入是 A4,GEMM 通常仍使用 FP32 累加,并输出 BF16/FP16;W4A4 只描述矩阵乘两侧的输入位宽。
优势
更低的量化误差
NVFP4 每 16 个元素重新缩放一次,并使用能表示非 2 的幂的 E4M3 Scale。相比更大 Block 或只允许 2 的幂 Scale 的方案,它通常能更准确地贴合局部分布,尤其能减弱异常值对同一 Tensor 中其他元素的影响。
更低的存储与带宽
两个 E2M1 值打包进一个 Byte,Weight 主体从 BF16 的 16 bit 降到 4 bit;加入局部 Scale 后理论成本约为 4.5 bit/element。更小的 Weight 和 Activation 可以减少显存占用与内存搬运,但模型整体收益还会受到高精度模块、KV Cache、Padding 和 Workspace 影响。
原生低精度计算
Blackwell Tensor Core 的 block-scaled MMA 可以直接读取 E2M1 数据和 E4M3 Scale,并使用 FP32 累加,无需先把完整 Weight Tensor 反量化为 BF16。这样存储、数据搬运和矩阵乘都能沿用低精度路径,而不只是压缩 Checkpoint。
与 MXFP4、INT4 对比
| 方案 | 数据 | 局部 Scale | 典型 Block | 常见配置 | 主要特点 |
|---|---|---|---|---|---|
| NVFP4 | E2M1 | E4M3 + FP32 全局 Scale | 16 | W4A4 | 局部拟合更细,Scale 元数据更多 |
| MXFP4 | E2M1 | E8M0,仅 2 的幂 | 32 | W4A4 | 格式更简单,Scale 元数据更少 |
| Group-wise INT4 | INT4 | Float Scale,可选 Zero-Point | 常见 128 | W4A16 | Weight-Only 生态成熟,但格点和计算路径不同 |
NVFP4 的核心优势不是“E2M1 比其他 4-bit 类型天然更准”,而是 16-element Block、E4M3 局部 Scale 与 FP32 全局 Scale 的组合。代价是每 16 个值需要额外保存 8-bit Scale,并对 Checkpoint 布局和 Kernel 提出更严格的要求。
使用边界
- 硬件:NVIDIA 原生 NVFP4 Tensor Core 路径主要面向 Blackwell;其他设备可以模拟或反量化执行,但不等于获得原生 FP4 吞吐。
- 模块覆盖:模型名带
NVFP4不代表所有 Tensor 都是 4 bit;Embedding、LM Head、Router、Normalization 或部分 Attention 常保留高精度。 - KV Cache:KV Cache 是独立量化对象,可以使用 BF16、FP8 或单独的 FP4 配置。
- 实际收益:不能仅按
推导 4 倍显存节省或加速;还取决于 Scale 开销以及高精度模块和非 GEMM 瓶颈。
具体数值类型、粒度和硬件指令见数值类型、量化配置和 NVIDIA MMA。