Qwen 模型是后量化:BF16 通过细粒度量化到FP8、不是INT8
传统的量化(Per-tensor)是整个矩阵共用一个缩放因子(Scale),容易因局部极值导致整体精度下降。这种方式通过“局部自适应”的缩放,极大缓解了量化误差,是 DeepSeek-V3 等模型能在 FP8 精度下保持高性能的关键技术之一。(小数更准,大数也能凑合表示)。在处理分布不均匀的大模型参数时,FP8 的这种非均匀特性显然更懂模型的“脾气”。它不是单一标准,通常有 E4M3(4 指数+3
1. BF16 和 FP16 的区别是什么?
两者都是 16 位(2 字节)的浮点数格式,但比特位的分配策略完全不同,导致了特性和用途的分野:
- FP16 (Half Precision):1 位符号 + 5 位指数 + 10 位尾数。
- 特点:尾数位多,近 1 附近的精度更高;但指数位少,动态范围小(约 5.96×10−85.96 \times 10^{-8}5.96×10−8 到 655046550465504)。
- 痛点:训练时梯度或激活值容易超出范围(溢出 NaN 或下溢为 0),通常需要配合“损失缩放(Loss Scaling)”使用。
- BF16 (Brain Floating Point):1 位符号 + 8 位指数 + 7 位尾数。
- 特点:指数位与 FP32 完全一致,动态范围与 FP32 相同(约 1.4×10−451.4 \times 10^{-45}1.4×10−45 到 3.4×10383.4 \times 10^{38}3.4×1038),不易溢出;但尾数位少,精度比 FP16 低。
- 优势:训练稳定性极佳,是目前大模型训练的主流默认格式。
简单说:FP16 重“精度”,BF16 重“范围/稳定性”。
2. FP8 是浮点数和INT8
FP8 是 8 位(1 字节)的浮点数格式。它不是单一标准,通常有 E4M3(4 指数+3 尾数)和 E5M2(5 指数+2 尾数)两种主流变体。
其核心优势在于极致的效率提升:
- 显存减半:相比 FP16/BF16,模型权重显存占用直接降低 50%。
- 吞吐翻倍:在支持 FP8 Tensor Core 的硬件(如 NVIDIA H100/Blackwell)上,FP8 矩阵运算(GEMM)的吞吐量通常是 FP16 的 2 倍。
- 抗离群值:相比于同是 8 位的 INT8(定点整数),FP8 因为有指数位,天然拥有更大的动态范围,对大模型激活值中常见的离群值(Outliers)更鲁棒,量化精度损失更小。
无论是 FP8 还是 INT8,它们底层都只有 8 个比特(bit),所以确实只能表示 28=2562^8 = 25628=256 个不同的数值(codewords)。
但这 256 个数字的分布规律不同,这正是 FP8 在大模型中表现优于 INT8 的核心原因:
- INT8(整数):均匀分布的 256 个点
INT8 将范围(比如 -128 到 127)线性等分。无论数值是大是小,相邻两个数之间的间隔(分辨率)是固定的。
- 问题:如果权重中存在几个特别大的“离群值”(Outliers,在大模型中很常见),为了覆盖这些大数,线性间隔会被迫拉大,导致普通大小的数值量化时精度损失严重(四舍五入误差大)。
- FP8(浮点):非均匀分布的 256 个点
浮点数的设计是“科学计数法”,它把 256 个坑位倾斜分配了:
- 接近 0 的区域:分配了更多的码字,间隔很小(高精度),适合表示大多数密集的普通权重。
- 远离 0 的大数区域:分配了较少的码字,间隔很大(低精度),但足够“接住”偶尔出现的离群值而不至于溢出。
- 以 E4M3 格式为例,它能表示的最大值约为 448,而 INT8 最大是 127,前者的动态范围更大。
虽然都是 256 个数,但 INT8 是“平均主义”(大家间隔一样),FP8 是“贫富不均”(小数更准,大数也能凑合表示)。在处理分布不均匀的大模型参数时,FP8 的这种非均匀特性显然更懂模型的“脾气”。
3. Fine-grained FP8 quantization (block size 128) 如何实现?
传统的量化(Per-tensor)是整个矩阵共用一个缩放因子(Scale),容易因局部极值导致整体精度下降。细粒度量化(Fine-grained / Block-wise)的核心思想是**“分块量化,每块独立缩放”**:
- 分块:将大的权重矩阵或激活张量切分成更小的块。对于 block size = 128:
- 1D 块(常用于激活):每连续的 128 个元素为一个块(如 shape 为
[..., 128])。 - 2D 块(常用于权重):每
128x128个元素为一个块(如 shape 为[128, 128])。
- 1D 块(常用于激活):每连续的 128 个元素为一个块(如 shape 为
- 计算 Scale:对每个块独立计算其缩放因子(通常是
max_abs_value / FP8_max_range),通常以 FP32 存储以保证精度。 - 量化:块内的每个元素除以该块专属的 Scale,然后转换为 FP8 存储。
- 计算:在进行矩阵乘法时,取出对应块的 FP8 值和 Scale,计算
FP8值 × Scale还原(或在硬件层面直接融合计算)。
这种方式通过“局部自适应”的缩放,极大缓解了量化误差,是 DeepSeek-V3 等模型能在 FP8 精度下保持高性能的关键技术之一。
4. “BF16 数据,FP32 精度计算”的混合精度策略。
- NVIDIA 的“计算模式” (Tensor Core 角度)
在 NVIDIA 的一些架构文档或 cuBLAS 设置中,有时会提到 “BF32” 作为一种计算模式(Compute Mode)。
它的逻辑是:输入是 BF16(节省带宽和显存),但计算时会把尾数补零提升到 FP32 的精度再进行乘加运算。
- 目的:既享受了 BF16 的数据传输和存储效率,又几乎拥有 FP32 的计算精度(因为指数位本来就和 FP32 一样)。这可以看作是“用 BF16 的内存,跑近似 FP32 的计算”。
- Intel 的 TMUL 单元 (AMX 技术)
在 Intel 第四代至强可扩展处理器(Sapphire Rapids)引入的 AMX(高级矩阵扩展)中,有一个特殊的tdpbf16ps指令。
这个指令的操作数通常是 BF16,但它内部的累加器(Accumulator)是 FP32 的。有时候在工业界交流中,这种“BF16 输入、FP32 累加”的单元或数据类型也会被简称为 BF32 模式。
更多推荐


所有评论(0)