mcpField
D
debug

debug

github.com/fcakyon开发43863 次安装今天更新
代码仓库

关于 debug

用于排查 ML 训练故障的 Skill,按证据收集、受控烟雾测试和明确标注不确定性的流程调查。面向诊断训练任务的 Agent,要求有工具输出支持后再判断原因。

主要功能

  1. 01五步证据优先流程
  2. 02检查进程、系统、GPU、磁盘和日志
  3. 03受控烟雾测试与单变量对照
  4. 04提供有证据的结论或不确定性报告

适用场景

  1. 01诊断 NaN、OOM、挂起或训练变慢
  2. 02调查损失或 GPU 利用率异常
  3. 03提出修复前检查日志与检查点

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/fcakyon/phd-skills --skill debug

安装后在 Claude Code 中输入/debug确认已加载。

详细介绍

调试:先取证,再行动

在 ML 调试中,代价最高的一类错误是仅凭看似合理的推测就断言原因,然后尝试用“修复”掩盖真正的问题。这项技能要求严格遵循以下顺序:探查 → 假设 → 冒烟测试 → 对照 → 断言。

当助手在没有工具输出佐证的情况下声称找到了原因时,Agentic Stop hook 会从 reason 路由到此处。

何时运行

用户刚刚说了以下任意内容:

  • “为什么 X 失败了/发散了/出现 NaN/OOM/卡住了/变慢了/崩溃了”
  • “loss 在上升”“指标看起来很奇怪”“GPU 利用率是 0”
  • “调试这个”“诊断”“排查故障”“调查这次运行”
  • 粘贴日志片段并询问哪里出了问题

五步协议

第 1 步:低成本探查

形成任何假设之前,先收集低成本证据。以下操作都不会耗费超过几秒:

进程状态:

ps aux | grep -E '(python|train|torchrun|accelerate)' | grep -v grep

进程还在运行吗?是僵尸进程还是已终止进程?是否有多个实例?

内核/系统事件:

dmesg | tail -100 # OOM kills, hardware errors, NFS errors
journalctl -xe --since "1 hour ago" | tail -50

GPU 状态:

nvidia-smi
nvidia-smi --query-gpu=utilization.gpu,memory.used,temperature.gpu --format=csv

GPU 到底在使用吗?“训练”期间 GPU 处于空闲状态,说明进程卡在数据加载上,或者已经退出。

磁盘/文件系统:

df -h /path/to/run-dir
du -sh /path/to/run-dir/*

磁盘空间耗尽了吗?检查点没有写入吗?

日志回溯: 读取训练日志最后几百行。不要只相信用户的总结,他们可能只是粗略浏览过。查找:

  • 异常回溯
  • 重复出现的“loss=NaN”或“grad_norm=Inf”
  • 提前停止的提示(运行可能已正常完成)
  • _最后_一次成功的 epoch/step(进度停在了哪里)

检查点状态:

ls -la /path/to/run-dir/checkpoints/

最近一次检查点是什么时候写入的?从它的大小能看出什么?空的 .pt 文件与一个写到一半的 2GB 文件情况不同。

第 2 步:提出假设(明确标注为假设)

探查之后,说明_可能_发生了什么,并明确表述为假设:

“假设:此次运行因 OOM 而失败,因为 dmesg 显示 3 分钟前发生了 oom-kill,且进程已消失。尚未排除的其他假设:(a) NFS 写入超时;(b) 被同级进程显式终止。”

绝不要直接跳到“原因是 X”。假设标签明确指出了你尚不确定的内容。

第 3 步:冒烟测试

确认或否定假设,成本最低的方法是在受控条件下复现故障特征:

  • OOM 假设:使用 batch_size=1 重跑 1 步。如果成功运行,则确认是 OOM;如果以相同方式失败,则说明并非 OOM。
  • 数据假设:使用内存中的合成数据集重跑。如果运行正常,则问题可能与数据路径有关。
  • 模型假设:仅对单个 batch 执行前向传播,并使用 eval() 模式。Loss 是有限值吗?输出正常吗?
  • 优化器假设:使用 lr=0 重跑。如果 loss 仍然爆炸,说明损失函数本身有问题(而不是优化器)。
  • 分布式假设:在 1 张 GPU 上重跑。如果运行正常,则问题可能与 DDP/NCCL 有关。

30 秒的冒烟测试胜过 30 分钟的重启祈祷。

第 4 步:对照

如果冒烟测试的结果不明确,就运行对照测试:只更改失败配置中的一个变量,然后重跑冒烟测试。差异有助于缩小可能的原因机制。

常见的对照维度(每次只更改一个):

  • 单源数据与多源数据
  • 默认 workers 与调整后的 workers
  • 开启与关闭混合精度
  • 开启与关闭梯度检查点
  • 开启与关闭 torch.compile
第 5 步:断言原因

只有在证据经过探查、冒烟测试和对照逐步累积之后,才能断言原因。断言应引用能够证明原因的具体工具输出:

“根因:NFS 写入超时。证据:dmesg 显示 14:23 出现 nfs server X not responding(与最后一次写入检查点的时间是同一分钟),且使用 batch=1 进行的冒烟测试重现了超时。建议的修复方法:为检查点绑定挂载本地临时目录,并在 epoch 结束时 rsync 到 NFS。”

如果证据没有逐步累积,就不要将假设升级为原因。应说明“我目前还不知道”,并提出下一步探查。

应避免的做法

  • “可能是 X,我试试 Y” → 不要这样做。先探查。
  • 通过做出小改动来重新运行,以此诊断问题。先进行冒烟测试,再有意重新运行。
  • 只引用用户的描述作为证据:重新阅读实际日志。
  • 当产物与之矛盾时,仍停留在第一个看似合理的原因上。

输出

一份简洁的诊断报告,包含:(1) 探查结果;(2) 假设;(3) 冒烟测试结果;(4) 原因或尚不确定的结论;(5) 建议的后续操作。每项判断都要引用支持它的工具输出。

评论

支持 Markdown