尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

分布式训练失败实验怎么记:对齐显存、通信与随机状态

分布式训练失败实验怎么记:对齐显存、通信与随机状态 分布式训练失败实验怎么记对齐显存、通信与随机状态分布式训练失败时单条SIGSEGV或 NaN 日志只能说明某个进程退出不能直接证明是显存、通信还是数据导致。先把实验缩到能稳定复现的最小规模。1. 把失败条件固定下来训练问题应拆成数值正确性、数据供给、显存使用和通信行为四部分。先以小规模、固定输入验证前向和反向结果再观察多进程路径避免把单一监控值当成整体结论。记录框架与 CUDA 版本、设备拓扑、启动命令、数据版本、Batch 形状、精度模式和随机状态。失败在哪个 rank 出现、其他 rank 如何退出也应放在同一时间轴上。2. 从单卡正确性走到多卡通信每次试验都应写清框架版本、设备类型、批量形状、随机种子和启动方式。发生偏差时优先比较中间张量与梯度而不是直接调整并行参数。先用小数据确认前向、损失和梯度有限再开混合精度最后加入多进程。这样即使实验仍然失败也能知道故障从哪一步开始出现。下面的日志字段由故障注入运行产生。3. 记录通信与梯度状态[ERROR] torch.distributed.elastic.multiprocessing.api: [rank3] Terminated with signal SIGSEGV [RANK 3] RuntimeError: Loss scaler received an inf or nan gradient value. Skipping step. [RANK 3] Overflow detected. Reducing loss scale from 65536.0 to 32768.0 ... [RANK 3] Overflow detected. Reducing loss scale from 0.0000305 to 0.0000152 -- Scale 缩到下限仍未恢复 [FATAL] RuntimeError: Loss scale reached minimum threshold (1e-5), training aborted.import torch import torch.nn as nn import torch.distributed as dist from typing import Dict, Optional class DistributedGradientSanitizer: 分布式梯度诊断与防护器。 挂载至 PyTorch 模型后可在梯度反向传播阶段实时捕获 Inf/NaN 并保存证据链。 def __init__(self, model: nn.Module, max_norm: float 1.0, dump_path: str /tmp/grad_dump.pt): self.model model self.max_norm max_norm self.dump_path dump_path self.history_norms: Dict[str, float] {} self._register_hooks() def _register_hooks(self): for name, param in self.model.named_parameters(): if param.requires_grad: # 使用闭包绑定参数名称 param.register_hook(self._create_hook(name)) def _create_hook(self, param_name: str): def hook(grad: torch.Tensor) - Optional[torch.Tensor]: # 1. 检查是否存在数值异常 if torch.isnan(grad).any() or torch.isinf(grad).any(): rank dist.get_rank() if dist.is_initialized() else 0 print(f[ALERT] Rank {rank} 检测到数值异常! 层名: {param_name}) # 2. 导出证据链快照 self._dump_evidence(param_name, grad, rank) # 3. 将 NaN/Inf 强制替换为 0防止全盘污染 Optimizer 状态 zero_grad torch.zeros_like(grad) return zero_grad # 4. 计算并纪录正常的 L2 范数 norm_val torch.norm(grad).item() self.history_norms[param_name] norm_val return grad return hook def _dump_evidence(self, param_name: str, bad_grad: torch.Tensor, rank: int): 保存诊断快照到磁盘 try: dump_data { rank: rank, failed_param: param_name, grad_snapshot: bad_grad.detach().cpu(), recent_norms: self.history_norms, timestamp: torch.cuda.Event() } target_file f{self.dump_path}.rank{rank} torch.save(dump_data, target_file) print(f[DUMP] 故障证据已成功写入磁盘文件: {target_file}) except Exception as e: print(f[ERROR] 保存证据链快照失败: {str(e)}) def clip_gradients_safe(self) - float: 带安全校验的梯度裁剪 if not dist.is_initialized(): return torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.max_norm).item() # 跨卡计算全局梯度的 Total Norm total_norm 0.0 for p in self.model.parameters(): if p.grad is not None: param_norm p.grad.detach().data.norm(2) total_norm param_norm.item() ** 2 total_norm total_norm ** 0.5 if total_norm self.max_norm: clip_coef self.max_norm / (total_norm 1e-6) for p in self.model.parameters(): if p.grad is not None: p.grad.detach().mul_(clip_coef) return total_norm[Rank 2] ALERT: Layer transformer.layers.24.mlp.w2 梯度出现 NaN! [Rank 2] DUMP: 证据记录写入 /tmp/grad_dump.pt.rank2 [Rank 0..63] 全局梯度 Clip 执行完毕Total Norm 由 142.8 截断至 1.0 [Scaler] 触发混合精度保护跳过本 Batch 权重更新连续 3 个 Batch 平稳后重新提高 Scale [Rank 0] Checkpoint 加载机制就绪训练流程继续向下推进4. 复核清单JDK、CUDA、框架、拓扑和启动命令是否齐全。单卡正确性与多卡通信是否分开验证。NaN 首次出现的 rank、step 与张量是否可定位。失败实验是否保留最小输入和恢复条件。总结“一次失败实验能说明什么”应以清晰的条件和脚本复核。先记录边界再解释结果。
返回列表