1. BF16 和 FP16 的区别是什么?

两者都是 16 位(2 字节)的浮点数格式,但比特位的分配策略完全不同,导致了特性和用途的分野:

  • FP16 (Half Precision):1 位符号 + 5 位指数 + 10 位尾数
    • 特点:尾数位多,近 1 附近的精度更高;但指数位少,动态范围小(约 5.96×10−85.96 \times 10^{-8}5.96×108655046550465504)。
    • 痛点:训练时梯度或激活值容易超出范围(溢出 NaN 或下溢为 0),通常需要配合“损失缩放(Loss Scaling)”使用。
  • BF16 (Brain Floating Point):1 位符号 + 8 位指数 + 7 位尾数
    • 特点:指数位与 FP32 完全一致,动态范围与 FP32 相同(约 1.4×10−451.4 \times 10^{-45}1.4×10453.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 的核心原因:

  1. INT8(整数):均匀分布的 256 个点
    INT8 将范围(比如 -128 到 127)线性等分。无论数值是大是小,相邻两个数之间的间隔(分辨率)是固定的
  • 问题:如果权重中存在几个特别大的“离群值”(Outliers,在大模型中很常见),为了覆盖这些大数,线性间隔会被迫拉大,导致普通大小的数值量化时精度损失严重(四舍五入误差大)。
  1. 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)的核心思想是**“分块量化,每块独立缩放”**:

  1. 分块:将大的权重矩阵或激活张量切分成更小的块。对于 block size = 128:
    • 1D 块(常用于激活):每连续的 128 个元素为一个块(如 shape 为 [..., 128])。
    • 2D 块(常用于权重):每 128x128 个元素为一个块(如 shape 为 [128, 128])。
  2. 计算 Scale:对每个块独立计算其缩放因子(通常是 max_abs_value / FP8_max_range),通常以 FP32 存储以保证精度。
  3. 量化:块内的每个元素除以该块专属的 Scale,然后转换为 FP8 存储。
  4. 计算:在进行矩阵乘法时,取出对应块的 FP8 值和 Scale,计算 FP8值 × Scale 还原(或在硬件层面直接融合计算)。

这种方式通过“局部自适应”的缩放,极大缓解了量化误差,是 DeepSeek-V3 等模型能在 FP8 精度下保持高性能的关键技术之一。

4. “BF16 数据,FP32 精度计算”的混合精度策略。

  1. NVIDIA 的“计算模式” (Tensor Core 角度)
    在 NVIDIA 的一些架构文档或 cuBLAS 设置中,有时会提到 “BF32” 作为一种计算模式(Compute Mode)。

它的逻辑是:输入是 BF16(节省带宽和显存),但计算时会把尾数补零提升到 FP32 的精度再进行乘加运算

  • 目的:既享受了 BF16 的数据传输和存储效率,又几乎拥有 FP32 的计算精度(因为指数位本来就和 FP32 一样)。这可以看作是“用 BF16 的内存,跑近似 FP32 的计算”。
  1. Intel 的 TMUL 单元 (AMX 技术)
    在 Intel 第四代至强可扩展处理器(Sapphire Rapids)引入的 AMX(高级矩阵扩展)中,有一个特殊的 tdpbf16ps 指令。

这个指令的操作数通常是 BF16,但它内部的累加器(Accumulator)是 FP32 的。有时候在工业界交流中,这种“BF16 输入、FP32 累加”的单元或数据类型也会被简称为 BF32 模式。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐