Loss NaN 噩梦:大规模训练中 Silent Data Corruption 问题解析
如果你有在大规模集群上训过大模型的话,你大概率会碰到过 Loss NaN 的问题。也许这种问题并不是很常见,但是一旦碰到,它往往非常难以排查。因为,Loss NaN 问题不仅可能是来自于算法,也可能来自于数据的不当输入,还有来自于硬件的计算错误。这种计算错误往往不会报错,被称作 Silent Data Corruption1234 问题。
Silent Errors within hardware devices occur when an internal defect manifests in a part of the circuit which does not have check logic to detect the incorrect circuit operation. The results of such a defect can range from flipping a single bit in a single data value, up to causing the software to execute the wrong instructions. Silent data corruptions (SDC) in hardware impact computational integrity for large-scale applications.2
当所有的这些问题交织在一起,当硬件永远能够计算正确的预期不再成立,当训练的规模扩大到千卡乃至万卡级别,恭喜你,你碰到了 bugs from hell 5 :)
SDC 问题并没有被研究清楚,并且随着芯片的先进制造工艺一步步逼近物理极限、以及机器学习训练等负载越来越大的计算规模,这个问题的严重性开始被社区所重视。2024 年,OCP 等社区开始号召研究机构、硬件厂商等对 SDC 问题采取行动67。
本文梳理了相关文献895101112,尝试去理解 Silent Data Corruption 问题,并阐述其在大规模训练中造成的影响和业界当前的解决方案。
Loss NaN 噩梦
如果你真正在千卡乃至万卡规模训练过大模型,你应该理解这里所说的 bugs from hell 的深刻含义:)
当出现 SDC 问题的时候,或者准确的说,当你开始意识到可能出现了 SDC 问题的时候,问题已经非常不好解决了。SDC 问题一个最典型的表现是,模型训练出现了 Loss NaN。然而,出现 Loss NaN 的时候并不知道是软件问题还是硬件问题,因为错误的算法设计和不合理的输入也可能造成 Loss NaN。
假设我们确定就是硬件的问题,我们面临的现状依然十分复杂,因为硬件的问题往往是 non-deterministic 非确定性的。对于程序员来说,一个基础的认知是,能够稳定复现的问题是好问题,当一个问题不能甚至都不能稳定复现,排查起来会非常痛苦。
不能稳定复现 non-deterministic 往往可能表现在多个层面:
- 同样的机器,可能有时候没问题,可能有时候有问题
- 同样的 deterministic 任务,可能问题暴露出来在不同的 iteration
同一个 deterministic 任务,同样的机器,在不同 step 发生 NaN - 对于机器学习任务,可能硬件上真正出现了 SDC 问题,但是在训练上看不到影响
loss 曲线,最可怕的不是 loss 爆炸,也不是 loss nan,而是 silent
- 对于机器学习任务,可能硬件上真正出现了 SDC 问题,但是在训练上看不到影响
好的,进一步减少问题的难度,假设我们现在有一个工具可以稳定的在坏机器上复现这个问题。以 NVIDIA 提供的 DCGM13 工具为例,其提供了 dcgmi diag -r 4 的工具可以检测出来绝大部分的硬件问题,包括 GPU CUDA/Tensor Cores 和 GPU Memory 以及 NVLink 等问题。
然而,这种检测工具目前并不高效。虽然它可以检测出来大部分的问题,但是往往耗时很久(比如 dcgmi diag -r 4 需要全集群停机跑 4 个小时以上)。对于一个万卡集群,这样去检查经济成本和时间成本都太大。或者,另一个经典方案是 二分大法,然而这个方法太过于耗时耗力,只能是最后什么方法都没有的压箱底方案,如果有更加高效的检测方案,排查起来会好的多。
为什么会 Loss NaN ?
在简单介绍了 Loss NaN 问题的困境之后,我们先来理解下 Loss NaN 的主要原因。
浮点数中 NaN 通常表示未定义或者不可表示的值:
软件和硬件问题都有可能造成 NaN:
- 软件问题
- 溢出或者精度问题:超出数值范围的计算可能导致 NaN
- 硬件问题
- 如果硬件上有 bit 翻转,比如 fp32 的 23 个尾数位,只要有一个 bit 翻转,数值就会变成 NaN
分析可能的具体软件问题:
- 梯度爆炸:
- 原因:可能学习率过高,导致在迭代的 100 轮以内,loss 随每轮迭代越来越大,最终超过了浮点型表示的范围,就变成了 NaN。
- 措施:降低学习率,设置 gradient clipping 等
- 不当的 loss 函数:
- 原因:有时候损失层中 loss 的计算可能导致 NaN 的出现。比如,给 InfogainLoss 层输入没有归一化的值,使用带有 bug 的自定义损失层等等
- 现象:观测训练产生的 log 时一开始并不能看到异常,loss 也在逐步的降低,但突然之间 NaN 就出现了
- 措施:看是否能重现这个错误,在 loss layer 中加入一些输出以进行调试
- 不当的输入:
- 原因:输入中就有 NaN
- 现象:每当学习的过程中碰到这个错误的输入,就会变成 NaN。观察 log 的时候也许不能察觉任何异常,loss 逐步的降低,但突然间就变成 NaN 了
- 措施:重整数据集,确保训练集和数据集里面没有损坏的图片等。调试中你可以使用一个简单的网络来读取输入层,有一个缺省的 loss,并过一遍所有输入,如果其中有错误的输入,这个缺省的层也会产生 NaN
- 涉及到指数计算
- 出现溢出,产生 INF 或者 NaN
Loss NaN 并不是最可怕的
尽管上述的 Loss NaN 问题已经非常难受了,有的时候,Loss NaN 可能并不是最可怕的问题。如下所图所示:
- 曲线一:梯度爆炸了,很容易确定一般是算法和工程上的问题
- 曲线二:NaN 了,至少知道有问题发生,而且有可能是硬件问题
- 曲线三:可能发生了错误,但是我们完全不知道,它可能是很多的计算中有一个小部分发生了错误。
- 错误悄无声息,会随着时间的推移慢慢积累,最终导致像曲线一训练失败
- 可怕的是,可能到发现问题的时间和具体产生错误的时间非常的久,我们不知道到底什么时候出错了
这一点在 The Adventure of the Errant Hardware1 和 Understanding and Mitigating Hardware Failures in Deep Learning Training Accelerator Systems8 中都有所提及:
硬件会出错吗?
当然!
在电子数字的世界里,所有的信息都是以简单的 0 与 1 表示;不过当数据在电子元件间进行传递时,是有可能发生数据 误传 的情形,也就是说原来该是 0 的比特数据,却被误植为 1 的比特数据,而产生错误。其可能发生的原因相当多,包括电子噪声、元件硬件上的问题,或是传输接口不稳等,都可能造成如此的结果。
硬件的具体出错可以分为两种:
- 硬错误:设备中的某些组件发生了永久的物理性损坏
- 比如:温度变化过大,电压应力或对内存带来的物理压力,电路老化
- 软错误:设备组件完好,设备出现逻辑性结果错误
- 比如:电压扰动、高能粒子冲击、宇宙射线、信号干扰
在服务器技术中,有个经典的 RAS 技术1415 来保证服务器的运行问题,而不损害数据完整性。这里的 RAS 分别指的是:
- Reliability
- Availability
- Serviceability
RAS 技术认可硬件中(包括 Memory/CPU/PCIe/UPI 等)出现问题是正常的,但是会通过各种技术保证即使硬件出现了问题,也能保证服务器的稳定运行。
Memory SDC 问题与 ECC 方案
以 Memory 为例,内存错误是普遍存在的,目前主要会通过 ECC 纠错码等技术来保证即使 Memory 出现了问题也能够不影响程序。
ECC1617,纠错码,通常使用 hamming 码来存储多余的纠错位,在读取数据的时候计算读取出数据的汉明码,与内存中额外存储的汉明码进行比对,如果数据不一致,则说明数据出现错误,此时再利用汉明码的排错原理,获取错误的比特位,进行修复。
通常使用 SECDED 单错误校正,双错误检测,可以检测和纠正一个损坏的位,而只能检测到两个损坏的位。
如果检测到两位错误,硬件会抛出故障,程序会崩溃并停止运行。这也就是我们经常碰到的:
|
|
在当前,因为 ECC 技术的广泛应用,Memory 的故障已经不再是最关键的问题。
CPU SDC 问题与 MCA 方案
CPU 的 RAS 主要指的是 MCA 机制,Machine Check Architecture:
- MSR,Model Specific Register
- 当 CPU 检测到不可纠正的 MCE(Machine Check Error)时,就会触发 Machine Check Exception
- 软件会注册相关的函数来处理这个 exception,在这个函数中会通过读取 MSR 来收集 MCE 的错误信息,然后重启系统
- 然由于发生的 MCE 可能是非常致命的,CPU 直接重启了,没有办法完成 MCE 处理函数;甚至有可能在 MCE 处理函数中又触发了不可纠正的 MCE,也会导致系统直接重启
- 当 CPU 检测到可纠正的 MCE,当可纠正的 MCE 数量超过一定的阈值时 - 会触发 CMCI(Corrected Machine Check Error Interrupt),此时软件可以捕捉到该中断并进行相应的处理
Intel 在 MCA 的基础上又推出了 EMCA,简单来讲它可以将 MCE 和 CMCI 转换成 SMI,让 Firmware(BIOS)可以先行处理,然后再丢给 OS。AMD 也有类似的机制,只是不叫 EMCA。
当前的 GPU/TPU/NPU 的 SDC 问题
同样的,目前机器学习中广泛使用的 GPU/TPU/NPU 中也存在 SDC 问题,只是目前业界还没有通用的解决方案。
以 Google 的 Gemini 技术报告18为例:在训练 Gemini 这个规模的模型时,他们预期每一两周会碰到一次 SDC 问题,目前他们已经实现 fully deterministic infrastructure ,通过 SDC scanner 和备机来解决这个问题。
好消息是,NVIDIA 在 Blackwell GPU 引入了 RAS Engine20,希望能够像 Intel Xeon 芯片一样提升自检能力。但是这种 RAS Engine 是否有效还没得到确认,另外目前大规模用的还是 A 100/H100 这样的芯片。
故障注入和传播实验
论文 Understanding and Mitigating Hardware Failures in Deep Learning Training Accelerator Systems8 对于 GPU 等硬件中出现比特反转对于机器学习负载的影响进行了研究:
- 硬件故障的特性是怎样的?
- 在机器学习负载中,硬件故障是如何传播的?
- 硬件故障在什么条件下,会真正触发应用的问题?
实验设计
选择 NVDLA,来自 NVIDIA 的工业级开源 DL Accelerator: NVDLA21,包含常见的:
- Compute units for element-wise, activation, pooling operations etc.
- 16 parallel compute units that perform MAC (Multiply-Accumulate) operations
- 512KB on-chip buffer to store layer inputs, weights, partial sums and layer outputs
- Sequencing units that control the dataflow of inputs and weights
比特翻转故障注入:包括各种不同地方的故障注入
工作负载:随机选择下面模型五层注入,采用 8 台 TPU 服务器:
论文声称其故障注入模型有 99% 的信心认为其准确性
比特反转注入实验结果
论文定义了几种典型的机器学习负载异常的 pattern:
- 瞬时错误
- 出现 NaN/INF
- 加速器利用率下降
- 加速器 Hang
- 短期错误(非常少)
- 多次出现 INF/NaN
- 潜在错误
- SlowDegrade: 缓慢 Loss 下降
- SharpSlowDegrade: Loss 出现毛刺下降
- SharpDegrade: loss 出现毛刺陡降
- LowTestAccuracy: 低测试准确率
对于选择的几种 workload,比特反转注入之后,具体异常表现为
结论一:
- 82.3 - 90.3% 实验,比特反转不显著影响训练 Loss
- 这其中的 65.5% - 86.3% 训练效果好于无故障案例
- 可能的原因是故障引入了噪声,引入了某些正则化效果
结论二:
- 2%-6% 实验训练 Loss 轻微抖动,通过增加 10%/17% 训练时间可恢复
结论三:
- 9.7% - 17.7% 实验影响训练,具体表现为上述的几种异常 Pattern
故障转播分析
论文对于比特反转故障注入的实验,进一步在机器学习负载中故障转播进行了理论分析。
故障传播路径:
- 如果故障发生在计算某层的权重梯度,故障就只会发生在这个点而不向后传播,此时这种故障对模型的影响有限
- 如果故障发生在计算激活值梯度,故障会沿着反向传播到最后一层,因此整个模型的梯度都会被影响
因此,如果可以在训练的时候检测特征值,具体的就是激活梯度等,有可能检测到对应的异常计算,并及时报警出来。
SDC 问题解决方案分析
本小节总结了目前业界对于 SDC 问题的主要解决方案:
| 分类 | 技术方向 | NV | Google (TPU) | Meta (GPU) |
|---|---|---|---|---|
| 系统级压测 | 离线压测/在线压测,关注覆盖率 | DCGM (NV) GPUBurn(生态) |
SDCChecker + Checkpoint 回滚 技术未公开 |
FleetScanner: 离线测试 Ripple:在线压测 |
| 基于特征值检测 | 关注提高检出率 | NA | 特征值(梯度历史比较)+ 跳过重新计算 | 激活梯度 Dr. DNA22 |
| 在线检测算子&容错 | 关注性能损失 | Making Convolutions Resilient Via Algorithm-Based Error Detection Techniques 论文 | NA | NA |
Google 在 HotChip 2024 23分享了他们对于 SDC 问题的分析和解决方案,正是通过 SDC Checker 来快速检测出问题机器,并结合调度编排系统 + Checkpoint 快速故障恢复。
对于 NV 则是依赖于 DCGM 工具来压测,对于华为 Ascend 则有对应的 DMI 工具。
对于 Meta,其综合了离线压测 FleetFunnel 和在线压测 Ripple 来检测出对应的坏机器
Adept 在 The Adventure of the Errant Hardware1 这篇博客中介绍了他们的经验。
1000s 内通过 deterministic 的任务能够检测出来坏机器:
Within the first 1000 seconds a machine produced a different result! With more experience, we know now this was typical. If an error is going to occur, our experience is that it usually happens within 1000 seconds, rarely within 10000 seconds and almost never after 10000 seconds. Replacing the machine and restarting the job led to a job that ran for weeks without encountering a NaN.
这里不同卡 TFLOPS 不同,跑同样的 deterministic 的任务,可能有的跑的快(比如 H100),有的跑的慢 (比如 L20),1000s 应该大致反映了通常能够检测出 NaN 的时间
矩阵计算有时候能够检测出来,但不总是能够。实际的 e2e 任务更能够检测出来,因为会涉及到全部的 GEMM/H2D/D2H/NCCL 等全方位压测:
Checking only the outputs of matrix multiplication will sometimes corroborate the finding, but sometimes it does not! A training run exercises the entire machine more thoroughly which surfaces additional problems (host to device transfer and vice versa, machine to machine communication, different memories and circuits inside the chip, etc.)
SDC 问题发生在不同阶段导致的结果不同。一个典型的机器学习流程如下所示:
- 如果故障发生在阶段 1,那么会在所有节点上都有一致的、错误的参数
- 如果故障的程度比较小,也就是 error 的值偏差比较小,可能对于 SGD 随机梯度下降而言这个错误可以自动恢复
- 如果故障的程度比较大,也就是 error 的值偏差比较大,可能造成比较大的训练问题。对于这种情况,Gradient Clipping 可能能够减轻一点故障的影响
- 如果发生在阶段 3,那么会有一个节点的参数不一致
- 可能从而引起梯度爆炸或者 Loss NaN
- 这种情况下可能的检测方法是对所有的参数和优化器状态每隔 N 次迭代做 checksum,然后检查是否互相一致
此外,Pytorch 社区也提出了 NaN checker 2425 来有效检测这种硬件故障带来的 Loss NaN 问题。
For distributed programs, it can also be the case that bad hardware causes NANs and finding the source of the NANs is as simple as raising an exception or crashing the particular rank that first observed a NAN. Since NANs can only flow between ranks/nodes by virtue of communication operations, it is possible to check for NANs only at the inputs to communications. Further, the check may not even need to be synchronous, as long as we can raise an error sometime soon after observing the NAN, allowing it to be enabled more frequently (or even on-by-default).
总结展望
本文梳理了目前对于 Silent Data Corruption 问题的相关研究,一般来说,我们期望硬件是不会出错的。然而,随着芯片制造工艺逐渐逼近物理极限,这种假设不再成立,有一些故障在 ICs 出厂时并没有被检测出来。尤其是对于现在大规模训练,这种问题带来了越来越多的问题,业界也提出了一些系统压测和特征值检测的方案来应对。
总的来说,这个问题并没有被很好的解决,OCP 等组织也发起了对 SDC 问题的相关研究,并资助了相关项目7,以期待该问题不要被传导到上层,或者能够更高效的被处理掉。
@article{loss-nan-sdc,
title = "Loss NaN 噩梦:大规模训练中 Silent Data Corruption 问题解析",
author = "Houmin, Wei",
journal = "In The Loop",
year = "2025",
month = "Jan",
url = "https://loop.houmin.site/context/silent-data-corruption"
}
-
The Adventure of the Errant Hardware, https://www.adept.ai/blog/sherlock-sdc ↩︎ ↩︎ ↩︎
-
Detecting silent data corruptions in the wild, https://arxiv.org/pdf/2203.08989 ↩︎ ↩︎
-
https://engineering.fb.com/2022/03/17/production-engineering/silent-errors/ ↩︎
-
Cores that don’t count, https://research.google/pubs/cores-that-dont-count/ ↩︎
-
Training in Turmoil: Silent Data Corruption in Systems at Scale, https://marcello.altervista.org/SLM.tttc-events.org/ITC%20Silicon%20Lifecycle%20Management%20Workshop%202021%20-%20Training%20in%20Turmoil.pdf ↩︎ ↩︎
-
https://www.opencompute.org/blog/computings-hidden-menace-the-ocp-takes-action-against-silent-data-corruption-sdc ↩︎
-
https://www.opencompute.org/blog/ocps-server-resilience-initiative-sdc-academic-research-awards-announced ↩︎ ↩︎
-
Understanding and Mitigating Hardware Failures in Deep Learning Training Accelerator Systems, https://dl.acm.org/doi/pdf/10.1145/3579371.3589105 ↩︎ ↩︎ ↩︎
-
Silent data corruptions at scale, https://arxiv.org/pdf/2102.11245 ↩︎
-
HAUBERK: Lightweight Silent Data Corruption Error Detector for GPGPU, https://tcipg.org/sites/default/files/papers/2011_Q1_RV1.pdf ↩︎
-
Silent Data Corruption (SDC) Vulnerability of GPU on Various GPGPU Workloads, https://s3.amazonaws.com/media.guidebook.com/upload/wugvwecR6s7glTn7eR3IceXqJOla1VUJYphsFxBk/764c1cf4-74c6-11e5-8ab0-0ef9706f2f71.pdf ↩︎
-
Estimating Silent Data Corruption Rates Using a Two-Level Model, https://arxiv.org/pdf/2005.01445 ↩︎
-
https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/dcgm-diagnostics.html#getting-started-with-dcgm-diagnostics ↩︎
-
H3C Intel G6 系列服务器 RAS 技术白皮书-6W104, https://www.h3c.com/cn/Service/Document_Software/Document_Center/Home/Server/00-Public/Learn_Technologies/White_Paper/H3C_G6_RAS_WP-14069/#_Toc180145663 ↩︎
-
https://peterhu.github.io/posts/2020/12/26/RAS%E7%AE%80%E4%BB%8B.html ↩︎
-
https://docs.nvidia.com/deploy/a100-gpu-mem-error-mgmt/index.html ↩︎
-
Gemini: A Family of Highly Capable Multimodal Models, https://arxiv.org/abs/2312.11805 ↩︎
-
The Llama 3 Herd of Models, https://arxiv.org/pdf/2407.21783 ↩︎
-
NVIDIA RAS Engine, https://www.nvidia.com/en-us/data-center/technologies/blackwell-architecture/ ↩︎
-
Dr. DNA: Combating Silent Data Corruptions in Deep Learning using Distribution of Neuron Activations, https://dl.acm.org/doi/10.1145/3620666.3651349 ↩︎
-
efficient nan-checker for distributed-collectives, https://github.com/pytorch/pytorch/issues/124348 ↩︎
-
No backlinks found.