满汉全席的后厨里,张师傅面对一百零八道菜,心里只装着一杆秤:每道菜该用多精细的量具?佛跳墙要电子天平称到毫克——这是 FP32,算得又稳又准;大锅乱炖一勺下去差不多就行——这是 FP16,速度快但精度粗。可要是全用天平,掌勺师傅得累趴下;全用大勺,招牌菜就得砸锅。真正的名厨会让两者各司其职:珍贵的步骤用精细量具,琐碎的重活交给大勺,再配上一口能一次翻炒十六片食材的“翻江铜锅”(Tensor Core),锅边的接汁盘还始终保持高精度。这套“该精则精、该快则快”的做菜哲学,就是混合精度计算的精髓——让每一步计算用最合适的数字格式,既保住味道,又省下灶火。

岗位关联

混合精度是 AI 工程师的“厨房管理课”:掌握它,你能让大模型训练提速 2-8 倍、显存减半,还不让模型“炒糊”——这是从调参选手走向性能优化专家的必修技能。

目录
  1. 可视化演示
  2. 精度格式揭秘
  3. 张量核原理
  4. 混合精度训练
  5. 混合精度推理
  6. 性能优化技巧
  7. 工程实践指南
  8. 前沿发展趋势
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

三步展示混合精度:浮点格式位结构(FP32/FP16/BF16符号+指数+尾数)、混合精度训练流程(FP32权重→cast FP16→TC计算→FP32累加→损失缩放)、性能对比(FP32 vs FP16 vs BF16 TFLOPS)。

本节配有交互动效(进入视口后自动加载,约 3KB)。

浮点格式位结构 S:符号位(1bit) E:指数位(决定范围) M:尾数位(决定精度) FP32: 1+8+23=32 | FP16: 1+5+10=16 | BF16: 1+8+7=16 BF16保持FP32范围,FP16精度更高但范围小。

精度格式揭秘

张师傅的灶台上有两样量具:一台电子天平,精确到毫克,就是 FP32;一把大号汤勺,一勺下去大概其,就是 FP16。佛跳墙的鲍汁必须用天平,而十锅乱炖的配菜用汤勺就够了。计算机里的浮点数,本质也是一把带刻度的“量勺”——用 1 位符号、若干位指数、若干位尾数来逼近一个实数。

FP32 用了 32 个二进制位,其中指数 8 位、尾数 23 位;FP16 只给指数 5 位、尾数 10 位,整体砍半。位数越少,量勺的“刻度”越粗:能表示的最大值变小、相邻数字之间的间隔变大。为什么 AI 敢用这么粗的勺子?因为神经网络对噪声天生钝感——撒胡椒粉多抖一下少抖一下,食客尝不出来。

把数字具体写开:FP16 最大约 65504,最小正规数约 6.1 乘以 10 的负 5 次方;FP32 最大约 3.4 乘以 10 的 38 次方。FP16 的动态范围只有 FP32 的“一截”,但它占用的显存和搬运带宽也只有一半。这就像用汤勺快速备菜——每勺误差虽大,但大锅菜最后调味时,主厨用天平补回关键几笔。

所以第一课很朴素:没有一把勺子能通吃所有菜——认清每道菜该用天平还是汤勺,是混合精度的起点。

VFP16=(−1)s×2(e−15)×(1+m210)V_{FP16}=(-1)^{s}\times 2^{(e-15)}\times\left(1+\frac{m}{2^{10}}\right)
FP16 用 16 位比特拼出任意实数:一位定正负,五位定尺度,十位定细节。
  1. 符号位s 为 0 时数值为正,s 为 1 时为负,相当于在数字前贴一个正负号标签。
    (−1)s(-1)^{s}
  2. 指数偏移e 是 5 位指数存储值(0 到 31),减去偏移量 15 后得到真实指数,让小数和超大数都能表示。
    2(e−15)2^{(e-15)}
  3. 尾数归一化m 是 10 位小数部分,除以 2 的 10 次方后与 1 相加,表示 1.xxx 形式的有效数字。
    (1+m210)\left(1+\frac{m}{2^{10}}\right)
  4. 整体拼接三部分相乘得到数值。对比 FP32 时偏移量变为 127、尾数变为 23 位,精度随之大幅提升。
    V=(−1)s×2(e−b)×(1+m2t)V=(-1)^{s}\times 2^{(e-b)}\times\left(1+\frac{m}{2^{t}}\right)

张量核原理

传统 GPU 核心像一位位厨师,每人每次只能颠一下勺——做一次乘加。张师傅的厨房里还有一件传家宝:一口“翻江铜锅”,一次能同时翻炒 16 片食材,再让汤汁沿锅壁滑进高精度收集槽。这口锅就是 Tensor Core,张量核心。

Tensor Core 是 Volta 架构起嵌入 GPU 的专用矩阵运算单元。它不理会单个数字,只认矩阵:一次指令完成一个 4×4×4 的矩阵乘加,数学上写作 D = A×B + C。A、B 是 FP16 输入,而累加结果存在 FP32 收集槽里——这正是它既快又不糊锅的秘密。

一次 4×4×4 的运算包含 64 次乘加,共 128 次浮点运算。普通 CUDA 核心做一次标量乘加只贡献 2 次浮点运算,想让 Tensor Core 干活,必须把数据排成它认识的“方阵”,并通过 mma.sync 这类专用指令触发。这也是为什么矩阵越大、形状越规整,收益越明显——方阵炖得越满,铜锅越划算。

记住这口锅的脾气:它只吃 FP16 的食材,却用 FP32 的接汁盘。厨房里没有玄学,每一处设计都是为了“快而不失准”。

Dij=∑k=14Aik×Bkj+CijD_{ij}=\sum_{k=1}^{4}A_{ik}\times B_{kj}+C_{ij}
一次指令等于 4×4 的 A 与 B 做内积,再叠加进 FP32 的 C——这就是“翻江铜锅”的完整动作。
  1. 行列定位D_ij 表示结果矩阵第 i 行第 j 列的元素,由 A 的第 i 行与 B 的第 j 列共同决定。
    DijD_{ij}
  2. 内积求和把 A 的第 i 行与 B 的第 j 列对应元素逐一相乘再累加,k 从 1 加到 4。
    ∑k=14Aik×Bkj\sum_{k=1}^{4}A_{ik}\times B_{kj}
  3. 累加器融合乘积直接累加进 C_ij 这一“接汁盘”中,整个过程以 FP32 完成,避免误差层层叠加。
    +Cij+C_{ij}

混合精度训练

汤炖淡了怎么办?张师傅的做法是先加浓缩高汤,等味道提起来再兑水还原。混合精度训练也面临一个“淡”的问题:当梯度数值小到 FP16 都表示不了时,就会直接归零,像盐味消失得无影无踪。

训练中权重更新依赖梯度,而梯度常常非常小(比如 10 的负 6 次方),远低于 FP16 能表示的最小正规数 6.1×10 的负 5 次方——过不了“刻度”就变成 0。于是框架把损失先放大一个倍数 s,让梯度随之变大、落进 FP16 的可表示范围;反向传播完成后,再把梯度除以 s,还原成真实大小。

除了损失缩放,还有两件护身符。其一是权重主副本:权重平时用 FP32 存一份“标准配方”,每次更新在 FP32 上完成,前向时才临时转成 FP16 使用——防止小数点后第 4 位被勺子抹掉。其二是动态缩放:如果连续若干步没有出现 inf 或 nan,s 就翻倍;一旦溢出就减半,像厨师随时调火候。三步合起来,就是 PyTorch 中 torch.cuda.amp.GradScaler 做的事。

所谓混合精度,从来不是“全都用低精度”,而是大锅用汤勺、高汤用天平——该放大时放大,该还原时还原,味道一分不差。

Ls=L×s,g=1s⋅∂Ls∂WL_{s}=L\times s,\qquad g=\frac{1}{s}\cdot\frac{\partial L_{s}}{\partial W}
先把损失乘大 s,算完梯度再除回 s:优化路径不变,但小梯度不再被 FP16 的刻度吞掉。
  1. 损失放大前向得到损失 L 后乘以缩放因子 s(通常从 2 的 8 次方起步),得到放大后的损失。
    Ls=L×sL_{s}=L\times s
  2. 反向传播对放大后的损失求梯度,梯度也被同倍放大,能够安全地用 FP16 表示。
    ∂Ls∂W\frac{\partial L_{s}}{\partial W}
  3. 梯度还原更新权重前再除以 s,数学上与直接对原损失求梯度完全等价。
    1s⋅∂Ls∂W\frac{1}{s}\cdot\frac{\partial L_{s}}{\partial W}

混合精度推理

堂食的满汉全席要摆盘、要仪式感,但外卖窗口的盒饭只要快和标准。推理就像外卖:模型已经学成,不需要再算梯度,只要把菜打包送出去。这时连 FP16 都显得奢侈,INT8 这种“标准饭盒”更合适。

所谓量化,就是把连续浮点数映射到 8 个二进制位能装的 256 个格子里。权重和激活从 FP32 变成 INT8,内存体积直接减到四分之一;而推理往往受制于从显存搬数据的带宽,数据搬得少了,吞吐自然上去,延迟自然下来。

量化不是简单把数字砍头:先统计每层激活的真实分布来定 r_max(校准),再把矩阵乘法变成整数乘加,必要时用 FP32 做反量化回到浮点。加上 Tensor Core 对 INT8 也有专门支持,推理时甚至能跑出 FP32 数倍的吞吐。代价呢?大约 1% 以内的精度损失,多数任务完全可接受——盒饭虽简,营养达标。

推理优化的哲学,是把力气花在“少搬数据”而不是“多算几遍”——标准饭盒减少了搬运次数,厨房出餐自然更快。

q=round⁡(rrmax⁡×127)q=\operatorname{round}\left(\frac{r}{r_{\max}}\times 127\right)
把连续实数装进 256 个整数抽屉,读取体积降到四分之一,代价是抽屉的格子变粗。
  1. 量化范围r 是原始浮点值,r_max 是该层数值的绝对值上限,二者相除得到归一化比例。
    rrmax⁡\frac{r}{r_{\max}}
  2. 映射到整数域乘以 127 后取整,把 -1 到 1 的实数压缩到 -127 到 127 的整数格子。
    ×127\times 127
  3. 取整函数round 完成四舍五入,得到最终的 INT8 量化值 q。
    round⁡(⋅)\operatorname{round}(\cdot)

性能优化技巧

为什么厨房瓶颈常常不是灶不够旺,而是厨师来回跑动太费腿?GPU 也有同样的“动线问题”:计算单元快如闪电,但数据从显存搬到计算单元的路上堵车。一次 FP16 矩阵乘的加速,一半来自算得快,一半来自搬得少。

矩阵乘法 A(M×K) 乘以 B(K×N) 的总浮点运算量是 2MNK。Tensor Core 一个周期吞吐 128 次浮点运算,而 FP32 的 CUDA 核心只有它的几分之一。但真正决定墙上时间的是“运算量 vs 搬运量”的配比。把数据从 FP32 降到 FP16,搬运字节数直接减半,这条“腿”立刻轻松。

提升 I 的招数有三板斧:一是算子融合,把多个 kernel 合并成一次执行,避免中间结果反复写回显存,相当于备菜、炒菜、装盘在同一条流水线上完成;二是减少 host 与 device 之间的拷贝,数据别在“店外”打转;三是用 profiling 工具(如 Nsight Compute)做动线分析,找出最堵的路段。很多模型换上混合精度后提升只有 1.5 倍而不是 8 倍,原因往往就是带宽堵住了灶台。

优化不是把灶火烧到最大,而是让每一勺食材少跑冤枉路——混合精度恰好是这条动线的第一块多米诺骨牌。

F=2×M×N×K,I=FBF=2\times M\times N\times K,\qquad I=\frac{F}{B}
运算量与搬运字节数之比 I,决定了程序是在等算力还是等带宽。
  1. 运算量统计矩阵乘法中每个输出元素需要 K 次乘加,共 MN 个元素,乘以 2 得到总浮点运算次数。
    F=2×M×N×KF=2\times M\times N\times K
  2. 搬运量统计B 表示从显存读取的数据字节数,输入矩阵、权重矩阵都要被读一遍,每个数占 4 字节。
    B=(M×K+K×N+M×N)×4B=(M\times K+K\times N+M\times N)\times 4
  3. 计算强度I 等于 F 除以 B,I 越大说明每个字节搬运都推动更多运算,程序越接近算力饱和。
    I=FBI=\frac{F}{B}

工程实践指南

任何名店的厨房都有一本作业手册:每道新菜出锅前必须有“试菜记录”。混合精度上线的第一原则,也是先建立可对比的基准,而不是直接全量切 FP16 看效果。

主流的做法是让框架自动管理:PyTorch 里用 torch.autocast 加 GradScaler,TensorFlow 里用 mixed_precision.set_global_policy('mixed_float16'),几行代码就能开启。但自动不等于无脑——BatchNorm、损失计算这类“娇贵”步骤通常要留在 FP32,模型的输入输出也要对齐精度。

工程上最常踩的坑有三个:一是收敛变慢或 loss 变成 NaN,多半是动态缩放没开对、或某些层精度敏感;二是复现困难,需要固定随机种子并显式设置精度策略;三是验证只看 loss,不看相对误差。规范做法是:先在 FP32 上跑出基线,再切混合精度,对比训练曲线与验证指标,确保两者差距在阈值内,才算“过审上菜”。

手册的意义不在于规定每勺放多少盐,而在于任何改动都有对照和记录——混合精度的工程化,是从“感觉能行”走向“证明可行”的那一步。

ϵ=∣yfp16−yfp32∣∣yfp32∣+δ\epsilon=\frac{\left|y_{fp16}-y_{fp32}\right|}{\left|y_{fp32}\right|+\delta}
相对误差是“试菜记录”的核心指标:衡量低精度食谱与标准食谱的味道差距。
  1. 绝对误差用相同输入分别跑 FP16 与 FP32 前向,得到两条输出,逐元素相减并取绝对值。
    ∣yfp16−yfp32∣\left|y_{fp16}-y_{fp32}\right|
  2. 归一化除以 FP32 输出的绝对值,把误差变成与数值大小无关的相对比例。
    ∣yfp32∣\left|y_{fp32}\right|
  3. 防除零分母加上一个极小量 δ(如 10 的负 8 次方),避免输出恰好为 0 时除零。
    +δ+\delta

前沿发展趋势

厨房永远在升级:电子秤变薄、灶火变旺,新的量具也在不断出现。混合精度的世界同样日新月异,新一代数字格式正从实验室走向灶台。

BF16(脑浮点)把指数位扩到 8 位、尾数压到 7 位,动态范围和 FP32 一样大,专门拯救“下溢”问题——像一支刻度更宽、但精度略粗的新汤勺。更前沿的是 FP8:以 E4M3(4 位指数 3 位尾数)和 E5M2(5 位指数 2 位尾数)两种形态登场,把训练中的矩阵乘也推上了 8 位快车道。

与此同时,自动混合精度(AMP)已成为 PyTorch、Megatron 等框架的默认能力,开发者甚至不需要手动标记哪些算子用 FP16。硬件上,从 Volta 的 4×4×4 到 Hopper 的更大矩阵块与 FP8 支持,张量核正在变成整个 AI 算力的“主灶台”。可以预见,未来精度不再是“选 32 还是选 16”,而是“每一步选最合适的那把勺子”,由编译器与硬件共同完成。

数字格式的演进,本质上一直在回答同一个问题:怎么用最少的比特,端出味道最正的一桌菜?这桌满汉全席,还在继续上菜。

VBF16=(−1)s×2(e−127)×(1+m27)V_{BF16}=(-1)^{s}\times 2^{(e-127)}\times\left(1+\frac{m}{2^{7}}\right)
BF16 保留了 FP32 的动态范围,把小数细节让位给指数——专治“梯度太小记不住”的病。
  1. 指数扩展e 是 8 位指数,偏移量同为 127,因此 BF16 能表示的最大值与 FP32 一致。
    2(e−127)2^{(e-127)}
  2. 尾数压缩m 只有 7 位,小数精度约为 FP32 的 1/16,但换来同等动态范围。
    m27\frac{m}{2^{7}}
  3. 适用场景训练中梯度过小时会被 FP16 吞掉,而 BF16 能接住它们,因此成为大模型预训练的新宠。
    VBF16=(−1)s×2(e−127)×(1+m27)V_{BF16}=(-1)^{s}\times 2^{(e-127)}\times\left(1+\frac{m}{2^{7}}\right)

AI 应用场景

大语言模型预训练

阶段:模型训练

解决的问题:175B 参数的模型如果用 FP32 训练,单卡显存根本放不下,且训练速度受限于显存带宽。混合精度让模型状态减半、吞吐提升 2-4 倍,是千亿模型能跑起来的前提。

具体案例:Meta 训练的 LLaMA 系列、国内的 GLM 与 Qwen 预训练均采用 BF16 混合精度。训练脚本中只需切换 autocast 与 GradScaler,就能让 700 亿参数模型在数千张 A100 上稳定跑完数月训练周期,损失曲线与 FP32 基线几乎重合。

实时推荐系统推理

阶段:模型推理部署

解决的问题:广告与推荐服务要求几十毫秒内返回结果,内存带宽是硬瓶颈。INT8 量化让模型体积缩小 4 倍,单机 QPS 提升数倍。

具体案例:某电商推荐模型从 FP32 切换到 INT8 后,单条推理延迟从 45ms 降到 12ms,AUC 仅下降 0.3%。配合 Tensor Core 的 INT8 矩阵指令和批处理,峰值 QPS 从 2000 提升到 7800。

边缘端目标检测

阶段:端侧部署

解决的问题:嵌入式设备显存常小于 4GB,FP32 模型放不下,且供电受限。INT8 量化加张量核加速,让实时检测在板端成为可能。

具体案例:无人配送车上的 YOLOv8 检测模型,经混合精度量化后帧率从 8 FPS 提升到 30 FPS,满足实时避障要求,整机功耗还降低了 40%。

Python 演示

python32 行
import torch def demo_fp32_accumulator():    """演示为何 Tensor Core 需要 FP32 累加器"""    n = 2000    tiny = torch.full((n,), 0.001)    acc16 = torch.zeros((), dtype=torch.float16)    acc32 = torch.zeros((), dtype=torch.float32)    for i in range(n):        acc16 = (acc16 + tiny[i].half()).half()        acc32 = acc32 + tiny[i]    truth = tiny.sum().item()    err16 = abs(acc16.item() - truth)    err32 = abs(acc32.item() - truth)    print("truth      = {:.4f}".format(truth))    print("fp16 accum = {:.4f}, err = {:.6f}".format(acc16.item(), err16))    print("fp32 accum = {:.4f}, err = {:.6f}".format(acc32.item(), err32))    print("fp32 err is {:.0f}x smaller".format(err16 / max(err32, 1e-9))) def demo_loss_scaling():    """模拟损失缩放对抗梯度下溢"""    scale = 65536.0    tiny_grad = 2e-5    min_fp16 = 6.1e-5    ok = tiny_grad >= min_fp16    scaled = tiny_grad * scale    print("raw grad = {:.2e}, representable in fp16 = {}".format(tiny_grad, ok))    print("scaled   = {:.3f}, safely in fp16 range".format(scaled)) if __name__ == "__main__":    demo_fp32_accumulator()    demo_loss_scaling()
目的:用两段小实验复现正文的核心原理——第一段对比 FP16 与 FP32 累加器的误差,解释 Tensor Core 为何用 FP32“接汁盘”;第二段演示损失缩放如何把小梯度推进 FP16 的安全区。
  1. tiny = torch.full((n,), 0.001)造出 2000 个极小数值,模拟矩阵乘中一个个等待累加的乘积项。
  2. acc16 = (acc16 + tiny[i].half()).half()每一步都强制转回 FP16,复现低精度累加器“每加一次丢一点精度”的过程。
  3. acc32 = acc32 + tiny[i]FP32 累加器原封不动保存总和,对应 Tensor Core 的“接汁盘”。
  4. err16 = abs(acc16.item() - truth)计算 FP16 累加结果与真实总量的绝对误差。
  5. print("fp32 err is {:.0f}x smaller".format(err16 / max(err32, 1e-9)))输出两种累加方式的误差倍数,直观看到 FP32 累加的优势。
  6. tiny_grad = 2e-5模拟一个 2×10 的负 5 次方的微小梯度,低于 FP16 最小正规数。
  7. scaled = tiny_grad * scale放大 65536 倍后梯度变为 1.31,稳稳落进 FP16 可表示区间。

常见误区

误区混合精度不就是把所有张量换成 FP16 吗?我给模型加一行 .half() 就能加速,还省一半显存。

正解混合精度的关键是“混合”二字:权重和优化器状态保留 FP32 主副本,只有前向计算用 FP16,损失和梯度还要经过缩放与还原。全部转 FP16 时,小梯度直接下溢成 0,模型可能完全不收敛,速度再快也没意义。

为何常见:看到“FP16 省一半显存、快一倍”的宣传,容易把“用低精度”错误简化为“都用低精度”,忽略了数值稳定性的代价。

误区只要显卡支持 Tensor Core,我的任何 PyTorch 代码都会自动变快。

正解Tensor Core 只对特定形状的矩阵乘加(如 4×4×4)和特定数据类型(FP16/BF16/INT8)高效,需要数据布局对齐并走到专用指令(mma.sync)才会触发。常规 FP32 标量运算、小矩阵或不规整形状根本用不上它,有时反而更慢。

为何常见:把硬件加速当成黑盒魔法,不理解指令级触发条件和数据布局要求。

误区把损失乘上 65536 再回传,模型学到的权重肯定和原来不一样了。

正解缩放只发生在反向传播环节,权重更新前会除以同一个因子。数学上 (1/s)·∂(sL)/∂W 等于 ∂L/∂W,与直接对原损失求梯度完全等价。它改变的是数值的“刻度”,而不是优化方向。

为何常见:只看到“乘一个数”这个动作,没注意到后面的“除以同一个数”,被表象的数值变换迷惑。

误区推理从 FP32 换成 INT8,精度肯定掉得一塌糊涂,我不敢在生产环境用。

正解经过校准、量化感知训练或蒸馏,多数视觉与推荐模型在 INT8 下的精度损失小于 1%。现代 GPU 的 INT8 张量核配合反量化,能同时保住速度与可用精度。当然,对数值极端敏感的任务仍需单独验证。

为何常见:把“表示精度低”等同于“任务精度差”,忽略了神经网络对量化的鲁棒性以及校准环节的补偿作用。

误区精度越高模型越准,训练应该用 FP64,混合精度是偷工减料。

正解神经网络训练对噪声有天然鲁棒性,FP32 已足够;FP64 在深度学习中几乎不提供额外收益,却要付出 2 倍以上显存和数倍时间。混合精度是工程权衡,不是偷工减料。

为何常见:沿袭科学计算“双精度越好”的直觉,不了解深度学习任务的数值容错特性。

面试题

Q1. FP16 的尾数部分占用多少个二进制位?

单选题 · easy

  • A.10位← 正确答案
  • B.23位
  • C.8位
  • D.5位

答案:A。FP16 的位布局为 1 位符号、5 位指数、10 位尾数,尾数决定有效数字的精细程度。23 位尾数属于 FP32,8 位是 FP32 与 BF16 的指数位数,5 位恰好是 FP16 的指数位而不是尾数位。

Q2. Tensor Core 单次执行矩阵乘加的规模是?

单选题 · easy

  • A.正方形4阶方阵
  • B.正方形8阶方阵← 正确答案
  • C.正方形16阶方阵
  • D.正方形2阶方阵

答案:B。以 Volta 为代表的 Tensor Core 单条矩阵指令执行 4×4×4 的矩阵乘加,即 A(4×4) 与 B(4×4) 相乘并累加到 C(4×4)。8 阶、16 阶方阵是 Ampere/Hopper 新架构或分块张量指令的规模;2 阶太小,浪费张量核的并行度。

Q3. 损失缩放的主要目标是?

单选题 · mid

  • A.防止梯度下溢为零← 正确答案
  • B.加快反向传播速度
  • C.减少模型显存占用
  • D.提升学习率上限

答案:A。梯度在反向传播中常常小到 10 的负 6 次方,低于 FP16 最小正规数 6.1×10 的负 5 次方,会直接归零。损失缩放先乘大因子 s,梯度被同倍放大落入可表示区间;更新前再除以 s 还原。它不加速前向、不省显存,也不改变学习率。

Q4. Tensor Core 累加结果保存在哪种精度?

单选题 · mid

  • A.FP64 超高精度累加器
  • B.FP16 低精度累加器
  • C.FP32 高精度累加器← 正确答案
  • D.INT8 量化累加器

答案:C。Tensor Core 的卖点正是“输入 FP16、累加 FP32”:矩阵乘积以 FP16 计算,结果在 FP32 累加器中逐项相加,既享受低精度的高吞吐,又避免累加误差累积。FP64 累加在 AI 芯片中极少见,INT8 是推理量化场景的配置。

Q5. 混合精度训练中权重主副本采用哪个精度?

单选题 · mid

  • A.BF16 精度副本
  • B.FP32 精度副本← 正确答案
  • C.INT8 精度副本
  • D.FP16 精度副本

答案:B。训练时权重先在 FP32 维护一份“主副本”,优化器更新都在 FP32 完成,前向时才转成 FP16 参与计算。这样可以防止多次 FP16 舍入把微小的权重更新抹掉。FP16、INT8 与 BF16 都不是标准的权重主副本方案。

Q6. 混合精度训练的标准流程包含哪些步骤?

多选题 · hard

  • A.保存 FP32 权重副本← 正确答案
  • B.对损失进行动态缩放← 正确答案
  • C.对卷积核随机膨胀
  • D.丢弃梯度直接更新

答案:AB。标准流程包含 FP32 权重主副本、损失缩放(动态 GradScaler)以及合适的优化器状态管理,对应 A 与 B。卷积核膨胀是空洞卷积的概念,与精度无关;丢弃梯度等于不更新权重,两者都不是流程中的步骤。

Q7. FP16 能表示的最大有限值约等于?

单选题 · easy

  • A.65504← 正确答案
  • B.32768
  • C.131072
  • D.16384

答案:A。FP16 最大有限值是 65504,对应指数位取满且尾数最大的情况。32768 是 2 的 15 次方,131072 是 FP16 溢出到无穷的边界,16384 是 2 的 14 次方。记住 65504,调试缩放因子和检查溢出时经常用到。

Q8. 关于混合精度推理,正确的理解是?

多选题 · hard

  • A.显著缓解带宽瓶颈← 正确答案
  • B.延迟可以明显降低← 正确答案
  • C.精度必然大幅下降
  • D.权重必须保持 FP32

答案:AB。推理阶段数据要从显存搬到计算单元,瓶颈常在带宽。FP16/INT8 让搬运字节数骤降,延迟与吞吐双双受益,A 与 B 正确。精度并非必然大跌,校准得当可控制在 1% 内;推理权重量化后就是 INT8,无需保持 FP32。

Q9. BF16 相比 FP16 的核心优势是?

单选题 · mid

  • A.小数精度更高更细
  • B.动态范围更接近 FP32← 正确答案
  • C.占用显存空间更小
  • D.运算符延迟更低

答案:B。BF16 用 8 位指数复刻 FP32 的动态范围,能容纳极小的梯度值,避免下溢;代价是尾数精度降为 7 位。FP16 尾数 10 位小数更精细,但范围窄。两者显存占用相同,运算延迟取决于硬件支持而非格式本身。

Q10. 验证混合精度训练效果时,正确做法包括?

多选题 · extreme

  • A.对比 FP32 基准相对误差← 正确答案
  • B.监测损失曲线收敛情况← 正确答案
  • C.检查梯度是否出现 inf← 正确答案
  • D.要求权重逐位完全相同

答案:ABC。科学验证包括:与 FP32 基线对比相对误差、观察训练与验证损失曲线是否一致收敛、检查梯度中是否出现 inf/nan 以确认动态缩放正常工作,对应 A、B、C。“逐位完全相同”是错误的预期——混合精度与 FP32 本就有微小差异,关键在指标是否可接受。