从 FP32、FP16、BF16、FP8、INT8 / INT4、loss scaling、overflow / underflow、kernel fusion、FlashAttention 到 profiler,理解模型计算怎样贴着硬件跑
| 层级 | 它控制什么 | 常见问题 | 继续看 |
|---|---|---|---|
| Tensor dtype | 数值范围、精度、显存占用和硬件路径 | 溢出、下溢、舍入误差、dtype 混用 | 张量 / 自动微分 |
| Tensor layout | 内存排列是否适合连续访问 | 非 contiguous、隐式拷贝、转置后慢 kernel | AI Infra / GPU |
| Operator | 模型数学语义:矩阵乘、softmax、norm、activation | 算子碎、数值不稳定、动态 shape 难优化 | Norm / Residual |
| Kernel | 真正跑在 GPU / NPU 上的低层程序 | launch 开销、带宽浪费、没有 fusion、版本不兼容 | 模型服务 / 网关 |
| Profiler | 告诉你时间和显存花在哪里 | 只凭直觉优化,结果优化错瓶颈 | 成本 / 性能 |
模型代码里的一个 matmul,最终不是抽象数学在运行,而是某种 dtype、某种内存布局、某个 kernel、某条硬件路径和某组数值误差一起在运行。
| 格式 | 直觉 | 优势 | 风险 / 边界 |
|---|---|---|---|
| FP32 | 传统训练里的高精度浮点 | 范围和精度都稳,调试基准可靠 | 显存和带宽成本高,Tensor Core 路径不一定最优 |
| TF32 | NVIDIA 上给 FP32 matmul 的 Tensor Core 快路径 | 多数训练不用改代码就能加速 | 精度低于真正 FP32,极敏感任务要验证 |
| FP16 | 低精度浮点,显存低、吞吐高 | 训练和推理都常用,Tensor Core 支持成熟 | 数值范围窄,容易 overflow / underflow,常要 loss scaling |
| BF16 | 接近 FP32 的指数范围,但尾数更短 | 比 FP16 更不容易溢出,大模型训练常用 | 尾数精度低,细微差异可能损失 |
| FP8 | 进一步降低 bit 的浮点格式 | 新硬件上训练 / 推理吞吐和显存优势明显 | 需要缩放、校准和硬件 / 框架支持,稳定性更依赖工程 |
| INT8 | 整数低精度量化 | 推理部署成熟,显存和带宽更省 | 校准数据、激活离群值和任务敏感性很关键 |
| INT4 / NF4 | 更激进的 4 bit 权重量化 | 本地部署、LoRA 微调和端侧场景很有用 | 质量退化更明显,kernel 和格式生态决定实际收益 |
FP16 的尾数还可以,但指数范围窄,容易溢出;BF16 的指数范围像 FP32,更抗溢出,但尾数更短。很多大模型训练偏爱 BF16,是因为它在稳定性和性能之间更省心。
| 对象 | 常见精度 | 为什么这样 | 风险 |
|---|---|---|---|
| Forward matmul | FP16 / BF16 / FP8 | 大部分 FLOPs 在矩阵乘,低精度能吃 Tensor Core | 激活范围异常时可能溢出或失真 |
| Accumulation | FP32 或更高精度累加 | 大量乘加会放大舍入误差,累加更敏感 | 累加精度不足会伤 loss 和 logits |
| Master weights | FP32 / BF16 | 参数更新要保留更稳定的权重状态 | 只保低精度权重可能让更新噪声变大 |
| Gradients | FP16 / BF16 + scaling 或 FP32 | 省显存和通信,但梯度可能很小 | underflow、NaN、梯度爆炸 |
| Optimizer states | FP32、BF16 或低精度 optimizer | Adam 动量和二阶统计很吃内存,也很影响稳定性 | 低精度状态可能改变收敛行为 |
| LayerNorm / Softmax | 常保更高精度或用稳定 kernel | 归一化和指数运算数值敏感 | 低精度 softmax 可能导致概率分布异常 |
Mixed precision 不是“全都换成低精度”,而是把高吞吐路径交给低精度,把最容易造成数值灾难的位置保留更稳的精度。
| 问题 | 发生什么 | 外部症状 | 治理动作 |
|---|---|---|---|
| Overflow | 数值超过 dtype 可表示范围,变成 Inf 或 NaN | loss NaN、gradient norm 爆炸、logits 异常大 | 降学习率、gradient clipping、BF16、稳定 softmax、监控激活范围 |
| Underflow | 很小的数被低精度截成 0 | 梯度消失、训练停滞、小概率 token 信号丢失 | loss scaling、保留高精度累加、检查梯度分布 |
| Rounding Error | 连续数被舍入到粗刻度 | 量化后某些任务掉分、logprob 排序改变 | 校准、混合精度、敏感层保高精度、任务回归 |
| Catastrophic Cancellation | 接近的数相减导致有效精度丢失 | 归一化、方差、loss 计算不稳定 | 稳定公式、epsilon、框架内置高质量 kernel |
| Non-determinism | 并行规约顺序不同导致结果微小差异 | 同配置重复跑有小差别,边界样本结果漂移 | 固定 seed、确定性 kernel、容忍数值误差区间 |
把 NaN 当作“模型玄学”。大多数 NaN 都能从学习率、坏 batch、梯度爆炸、低精度溢出、softmax / norm 数值不稳和异常 kernel 路径里找到证据。
| Kernel 类型 | 负责什么 | 优化点 | 常见风险 |
|---|---|---|---|
| GEMM / MatMul | Linear、QKV、MLP、LM head 的核心计算 | Tensor Core、tiling、低精度、batching | shape 不友好、dtype 不匹配、没有吃到快路径 |
| Softmax | attention 权重和概率归一化 | 数值稳定、block 级规约、融合 | overflow、长序列显存读写重 |
| LayerNorm / RMSNorm | 尺度控制和归一化 | 融合、减少读写、高精度统计 | 低精度统计导致尺度漂移 |
| Activation | GELU、SiLU、SwiGLU 等非线性 | 和 matmul / elementwise 融合 | 小 kernel 过多导致 launch 开销 |
| Attention Kernel | QK、softmax、V 聚合 | FlashAttention、减少中间矩阵落显存 | mask、长上下文、dtype 和版本兼容 |
| Quantized Kernel | 低 bit 权重 / 激活的推理执行 | dequant 融合、group size、硬件指令 | 格式支持不一致,理论压缩不等于真实加速 |
GPU 很快,但从显存反复读写很贵。把多个小算子融合成一个 kernel,可以减少中间张量落显存、减少 kernel launch 开销,也能让数据在更靠近计算单元的地方停留更久。
| 普通 Attention 痛点 | FlashAttention 思路 | 收益 | 边界 |
|---|---|---|---|
| QK 矩阵随序列长度平方增长,中间结果很吃显存 | 分块计算 attention,不把完整 attention matrix 写回 HBM | 长上下文 prefill 更省显存、更快 | 不同 mask、dtype、硬件和框架版本影响可用性 |
| Softmax 需要数值稳定处理 | 在线 softmax 维护 max / sum,保证分块结果等价 | 减少 overflow 风险,同时降低读写 | 实现复杂,调试难度高 |
| 内存带宽而不是 FLOPs 成为瓶颈 | 提高数据复用,减少 HBM 访问 | 让 attention 更贴近硬件有效路径 | 不代表所有模型瓶颈都会消失 |
FlashAttention 不是换了 attention 数学,而是用更聪明的 kernel 实现同样的 attention 计算,核心收益来自减少显存读写和中间结果。
| 症状 | Profiler 里先看 | 可能原因 | 动作 |
|---|---|---|---|
| GPU 利用率低 | CPU 时间、数据加载、kernel 间空隙 | 数据管线慢、小 kernel 太多、同步点 | 预取、融合、减少同步、增大 batch |
| 显存占用高 | activation、workspace、KV Cache、临时张量 | 序列太长、未关闭梯度、隐式拷贝 | checkpointing、inference mode、layout 修正 |
| matmul 慢 | GEMM shape、dtype、Tensor Core 利用 | 维度不友好、dtype 不对、batch 太小 | 调整 shape、启用混合精度、合并小 batch |
| attention 慢 | prefill 时间、attention kernel、序列长度 | 没有 FlashAttention、mask 特殊、上下文过长 | 启用优化 kernel、压缩上下文、分流长请求 |
| 推理吞吐不稳 | batch 调度、KV Cache 水位、P95 / P99 | 长短请求混跑、显存碎片、队列策略差 | continuous batching、Paged KV、请求分池 |
| 场景 | 故障 | 优先怀疑 | 验证方式 |
|---|---|---|---|
| 预训练 | loss spike 或 NaN | 坏 batch、学习率、FP16 overflow、norm / softmax 不稳 | 回放 batch、查 loss scale、gradient norm、激活范围 |
| SFT / 微调 | 格式突然不稳 | 低精度误差、数据模板混乱、LoRA 合并误差 | FP32 / BF16 / 量化版本对比固定样本 logits |
| 推理服务 | 同模型换引擎输出略变 | kernel、dtype、sampling、tokenizer config 差异 | 固定 seed、固定输入、比较 logits 和 top token |
| 量化部署 | 代码 / 数学能力明显掉 | 敏感层被低 bit、激活离群值、校准集不覆盖 | 按任务切片回归,敏感层回高精度 |
| 长上下文 | 远距离引用退化 | KV Cache 精度、attention kernel、position scaling | needle 测试、KV 精度对照、长短上下文分桶 |
混合精度问题要能同时落到 dtype、loss scale、kernel 路径、profiler 事件、请求 Trace 和模型网关证据上,不能只凭“换成 BF16 就好了”来判断。线上慢、贵、输出漂移或 NaN,要能回到 AI 证据包索引 的模型服务与 Infra 证据、生成运行时证据和 Release Gate 证据。
| 证据节点 | 必须记录字段 | 用来排查什么 |
|---|---|---|
| request_runtime | request_id、model_id、engine_version、gpu_type、queue_ms、prefill_ms、decode_ms、tokens_per_second | 慢、卡、吞吐抖动是请求形态、队列、prefill、decode 还是硬件池造成的 |
| precision_policy | compute_dtype、param_dtype、grad_dtype、accumulation_dtype、quantization_config、sensitive_op_list | 哪些算子低精度,哪些路径保高精度,量化或 dtype 改动是否覆盖敏感层 |
| stability_event | loss_scale、overflow_count、nan_inf_event_id、grad_norm、bad_batch_id、activation_range | 训练崩坏是否来自溢出、下溢、异常样本、激活范围或低精度统计 |
| kernel_trace | kernel_name、backend_version、flash_attention_mode、fallback_reason、deterministic_flag、logits_diff | 性能和输出差异是否来自 kernel 命中、后端实现、规约顺序或确定性设置 |
| profiler_snapshot | profiler_run_id、top_ops、memory_bandwidth、tensor_core_utilization、sync_point、optimization_note | 瓶颈是算力、带宽、同步点、隐式 dtype 转换还是没有吃到 Tensor Core 快路径 |
| release_connection | eval_run_id、regression_slice、release_gate_id、rollback_engine_version、fixed_artifact_id | 引擎、kernel、dtype 或量化变更是否经过质量、成本、延迟和安全回归 |
张量页解释计算图,优化器页解释训练动力学,AI Infra 页解释硬件与服务底座,压缩页解释模型怎样变小。本页站在它们之间,解释 dtype、数值范围、kernel、内存访问和 profiler 如何把抽象模型变成真实硬件上的稳定训练和高效推理;进入生产后,这些差异要继续落到请求 Trace、模型网关证据、LLMOps 指标和发布闸门里。