| title | 调试漏斗 | ||
|---|---|---|---|
| created | 2026-07-10 | ||
| updated | 2026-07-10 | ||
| type | guide | ||
| tags |
|
||
| sources |
- 同时出现两个以上互相独立的根因猜测。
- 想通过反复重启、修改多个文件或“跑一次看看”来碰答案。
- 同一方向已经失败两次,但仍准备换一种写法继续试。
从用户入口沿真实 owner 读取到失败位置:配置、请求转换、调度、核心实现、输出和验收。先找分叉点和 contract,不从报错字符串直接跳到修法。
根因闭环的停止条件是:用户观察到的错误值有明确来源,源码能解释它怎样到达失败位置,现有校验为何没有阻止它,并且证据足以决定主要修复位置。满足后立即记录结论和时间;commit 历史、外围 warning、完整版本考古和不改变修复位置的排除项放到后续按需调查,不能继续占用根因收敛阶段。
静态检查通常先于昂贵实测:
- 搜索符号和配置字段;
- 读取调用方与消费方;
- 对比相邻成功路径;
- 查看当前 diff 和最近相关改动;
- 用最小日志确认实际分支。
列出所有候选,并为每个候选写一个最便宜的反证。优先排除能通过一处 source、一个配置值或一条日志证伪的解释。
只有一个候选明显领先时才修改代码。仍有多个候选时,先收集能区分它们的证据,不同时修多个位置。
运行前写清:
假设:
唯一变量:
预期证据:
什么结果会证伪:
运行后不能回答“这次排除了什么”,说明实验范围过大或证据设计不完整。
- 现象:沿真实路径查证。
- 诊断:把它作为高优先级候选,补最小证据。
- 明确修法:在目标和修改点没有歧义时直接执行,但仍满足安全、仓库和验证门禁。
不要把一句诊断自动扩张成多个文件、多个接口和新的公开 contract。
同一解释下两个独立尝试都失败时,停止换 API 或补 patch。重新检查:
- 真实输入类型、shape 和值;
- 当前走到的分支;
- 默认值在哪一层被改写;
- 报错中的常量或字段来自哪个配置;
- 对照实现是否真的具有同一 contract。
复杂框架错误尤其不能假设 tensor、position、batch 或设备维度遵循常见形状;先看真实调用方和 runtime 证据。
满足以下条件再进行昂贵运行:
- 目标路径已确认;
- 只验证一个主要假设;
- 输入和环境与用户问题一致;
- 有明确成功、失败和清理条件;
- 结果会改变下一步决策。
如果 source 已经能直接证明 contract mismatch,不要为了“更踏实”先启动完整服务。