mcgatom/codex-cannbot/model-infer-precision-debug

Claude Code and agent skill by mcgatom/codex-cannbot

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

基于 PyTorch 框架的昇腾 NPU 模型推理精度问题诊断技能。当前主要覆盖 KVCache / FlashAttention 相关精度问题,包括 Prefill/Decode 对齐、cache 更新错误、slot/block mapping 错误、attention 路径切换后的精度异常等。触发场景:优化改造后精度验证未通过、模型输出与基线存在显著偏差、Prefill 和 Decode 精度表现不一致、出现 NaN/Inf、量化模式下精度异常放大等。

Install

npx vskill@latest install mcgatom/codex-cannbot/model-infer-precision-debug

SKILL.md

推理精度问题诊断技能

当前主要覆盖 KVCache / FA 相关精度问题,其他推理精度问题后续补充。
不覆盖运行时错误(crash、hang、OOM、算子约束违反等见 model-infer-runtime-debug)。

按"症状分类 → 快速验证 → 分模块定位 → 逐层对比 → 陷阱修复"的分层策略排查精度问题。完整校验工具见 references/fa_debug_utils.md。

部署模式适配:诊断流程对框架部署 / 独立部署两模式均适用,差异仅在参数获取路径——框架部署从 forward_metadata.{block_table, slot_mapping, actual_seq_lengths_*, is_prefill} 取,独立部署从 Runner 自管的 ParallelContext / forward_metadata 实例取。block_table / slot_mapping 在框架部署下是 Dict[attn_type → Tensor],attention 内按 self.attn_type 取出对应 tensor;独立部署 Runner 自管的形态是单 Tensor。
packed sequence 协议(框架部署 modeling 强制要求):input_ids / position_ids 是 [TotalTokens] 一维;hidden_states 全程保持 [TotalTokens, hidden_size] 二维(不要 reshape 成 [B, S, H]);阶段分支统一用 forward_metadata.is_prefill。详见 model-infer-kvcache skill §3.1。
sparse_mode 写法(按路径分类):标准 LLM TND PA 路径 Prefill + Decode 统一 sparse_mode=3 + causal mask;滑窗层 Prefill + Decode 统一 sparse_mode=4 + band mask;MLA absorb 路径 Prefill sparse_mode=3 / Decode sparse_mode=0+mask=None。详见 model-infer-kvcache skill §2.7。

重要原则

  • 对比驱动:所有精度判定必须基于与基线(eager 模式 / 优化前)的数值对比,不可凭直觉
  • 逐步缩小范围:先定位阶段(Prefill/Decode)→ 再定位模块(KVCache 写入/FA 计算/后处理)→ 最后定位参数
  • 最小改动验证:每次只修改一个变量,验证后再进入下一个
  • 保留现场:调试过程中的中间 tensor 和日志必须保留,用于后续分析
  • 实际执行测试:所有调试步骤由 Agent 实际执行,不将测试工作委托给用户

排查工作流

接到精度调试任务后,按以下步骤执行:

第一步:收集信息 — 获取精度症状、优化阶段、执行/量化模式、基线输出

第二步:快速诊断 — 根据症状分类表判断方向 → 执行快速验证清单(含 FA 入参检查)→ 发现问题直接修复

第三步:分模块定位 — 二分法确定 Prefill/Decode → 针对性插桩验证 → PA 场景执行专项排查

第四步:精细定位(按需) — 使用逐层对比框架,dump 基线 → compare 优化后 → 定位首次偏差层

第五步:修复与验证 — 参照常见陷阱表修复 → 重新运行完整精度验证

第六步:输出调试报告 — 问题概要、根因分析、修复措施、修复验证、遗留风险


第二步:快速诊断

2.1 症状分类
症状可能原因优先排查方向
输出全为重复 token 或乱码KVCache 写入位置错误slot_mapping 构造 / 写入算子(PA 用 npu_scatter_nd_update_,BSH legacy 用 scatter_update_)
首个 token 正确,后续偏移Decode 阶段 kv_len 更新错误kv_len 生命周期
Prefill 正确,Decode 偏差大Decode FA 入参错位(按路径分类:MLA absorb Decode 应切 sparse_mode=0 / mask=None;标准 LLM TND PA 保持与 Prefill 同 sparse_mode=3)sparse_mode 路径分类 / actual_seq_lengths_kv
输出含 NaN/Inf数值溢出scale 参数、dtype 不匹配
精度逐层累积偏差FA 算子数值精度input_layout / NZ 格式 / 量化参数
多 batch 部分样本错误batch 间缓存交叉污染block_table / slot_mapping 构造
量化模式下偏差显著放大量化参数不匹配dequant_scale / antiquant_mode
2.2 快速验证清单
  • [ ] 1. dtype 一致性:KVCache tensor 与模型计算 dtype 一致(BF16 / FP16)
  • [ ] 2. device 一致性:所有 tensor 均在 NPU 上,无意外的 CPU tensor
  • [ ] 3. block_table dtype:必须为 torch.int32
  • [ ] 4. sparse_mode 按路径正确:标准 LLM TND PA Prefill+Decode 统一 3;滑窗层统一 4;MLA absorb Prefill 3 / Decode 0(详见 model-infer-kvcache §2.7)
  • [ ] 5. Prefill 和 Decode 的 FA 调用参数按路径配置(atten_mask、actual_seq_lengths 等;阶段分支取自 forward_metadata.is_prefill)
  • [ ] 6. scale 参数:1.0 / sqrt(head_dim),确认 head_dim 值正确
  • [ ] 7. num_heads / num_kv_heads:与模型配置一致,多卡时已按 rank 切分(num_kv_heads_per_rank = max(num_kv_heads // attn_tp_size, 1))
  • [ ] 8. kv_len 初始值:Prefill 后 kv_len 等于输入序列长度,非 0
  • [ ] 9. input_layout 与 tensor shape 匹配(标准 LLM TND PA 默认 TND;MLA absorb 用 TND_NTD)
  • [ ] 10. actual_seq_lengths 构造方式与 layout 匹配(TND 用 cumsum,BSH 用原值;框架部署对应 forward_metadata.actual_seq_lengths_cu_q / actual_seq_lengths_kv)
  • [ ] 11. atten_mask 与 sparse_mode 匹配(详见附录 F.1);MLA absorb Decode 用 None
  • [ ] 12. FA v1 vs v2 参数名:未混用(详见附录 F.2)
  • [ ] 13. PA 场景下 mask 最后一维 >= block_table 第二维 × block_size
  • [ ] 14. MLA rope 参数:query_rope/key_rope 同时传或同时不传;rope D=64,query D 仅支持 512/128
  • [ ] 15. inner_precise 行无效:Prefill + 自定义 mask 有全遮蔽行时需设为 2/3
  • [ ] 16. kv_len 层内只读:kv_len 在 attention/cache 内部未被修改(禁止层内递增,否则各层写入位置错位导致精度彻底损坏)
  • [ ] 17. hidden_states 全程保持 [TotalTokens, hidden_size] 二维形态,未被 reshape 成 [B, S, H](变长 batch 不能简单 reshape)

第三步:分模块定位

3.1 排查策略:二分法定位
模型输出与基线不一致
│
├─ 1. 仅运行 Prefill,对比输出
│ ├─ Prefill 输出一致 → 问题在 Decode 阶段(跳到 3.3)
│ └─ Prefill 输出不一致 → 问题在 Prefill 阶段(跳到 3.2)
│
├─ 2. Decode 第 1 步 vs 第 N 步
│ ├─ 第 1 步就不一致 → FA 入参或 KVCache 初始状态问题
│ └─ 第 N 步开始不一致 → kv_len 累计更新或缓存溢出问题
│
└─ 3. 逐层对比(跳到第四步)
3.2 Prefill 阶段精度排查

KVCache 写入验证:在写入算子(PA 模式 npu_scatter_nd_update_ / MLA 融合写入 npu_kv_rmsnorm_rope_cache / BSH legacy 骨架 scatter_update_)调用前后插桩,检查:

  1. 写入前缓存是否为零(首次 Prefill)
  2. 写入后缓存内容与 key_states 是否一致(阈值 1e-6)
  3. PA 路径:cache / states 都需 view 为 [total, num_kv_heads, head_dim];slot_mapping 取 forward_metadata.slot_mapping[self.attn_type].view(-1, 1)
  4. BSH legacy 路径:scatter_update_ 的 axis 与 layout 匹配(BSH → axis=1)

FA 入参验证:打印并校验 Q/K/V shape、actual_seq_qlen/kvlen、sparse_mode、是否含 NaN/Inf

3.3 Decode 阶段精度排查

KVCache 写入验证:

  1. 验证 slot_mapping 计算(独立部署连续缓存:expected_slot = kv_len.view(-1,1) + kv_len_offset;PA 模式:框架部署由 prepare_slot_mapping() 生成,独立部署 Runner 自管按 block_table 索引构造)
  2. 验证写入位置未越界
  3. 验证 kv_len 逐步递增正确

FA 入参验证(按路径分类):

  1. 标准 LLM TND PA:sparse_mode=3 + causal mask(与 Prefill 一致)
  2. 滑窗层:sparse_mode=4 + band mask + pre_tokens=sliding_window
  3. MLA absorb Decode:sparse_mode=0 + mask=None
  4. actual_seq_qlen 每个值通常为 1(MTP 场景为 next_n+1)
  5. block_table dtype 必须为 int32
  6. KV cache 已写入区域无 NaN/Inf
3.4 分页注意力(PA)专项排查
  1. block_table 静态校验:numel == batch_size × (max_seq_len // block_size)
  2. block_table 值域校验:应为 [0, total_blocks) 的排列,无重复
  3. slot_mapping 与 block_table 交叉验证

第四步:逐层精细对比

4.1 逐层对比框架

在 Transformer Block 的 8 个关键位置插入 checkpoint,与基线对比:

序号位置重要程度
1Block 输入普通
2Attention Norm 后普通
3QKV 投影后普通
4RoPE 后普通
5KVCache 写入后关键
6FA 输出关键
7Attention 残差后普通
8Block 输出普通

对比指标(均转为 float32 计算):max_abs_diff / max_rel_diff / cosine_similarity

判定阈值:BF16 模式 max_rel < 1e-3,量化模式 max_rel < 1e-2

使用流程:dump 基线 → compare 优化后 → 定位首次出现偏差的层和位置


第五步:常见精度陷阱与修复

5.1 KVCache 写入相关
问题根因修复方案
缓存写入位置偏移(PA 模式)npu_scatter_nd_update_ 的 cache / states view 形态不一致或 slot_mapping 索引错误cache 和 states 都 view 为 [total, num_kv_heads, head_dim];slot_mapping 取 forward_metadata.slot_mapping[self.attn_type].view(-1, 1)
缓存写入位置偏移(BSH legacy 骨架)scatter_update_ 的 axis 与 layout 不匹配BSH → axis=1
多 batch 缓存交叉写入(独立部署)kv_len_offset 未按 max_seq_len 对齐kv_len_offset = arange(0, batch*max_seq_len, max_seq_len)
Prefill 后缓存部分为零kv_len 计算错误检查 kv_len 是否等于实际有效序列长度(具体值视框架约定)
NZ 格式下缓存异常cache_mode 设置错误PA 模式使用 cache_mode="PA_NZ"
融合写入算子结果不一致npu_kv_rmsnorm_rope_cache 参数不匹配对齐 epsilon(用 kv_a_layernorm.variance_epsilon 而非硬编码)和 RoPE 频率
5.2 FA 算子相关
问题根因修复方案
MLA absorb Decode 偏差大Decode 仍用 sparse_mode=3 + causal maskMLA absorb Decode 切 sparse_mode=0 + atten_mask=None
标准 LLM Decode 偏差Decode 误改成 sparse_mode=0 + mask=None标准 LLM TND PA 路径 Decode 保持与 Prefill 一致 sparse_mode=3 + causal mask
滑窗层 Decode 偏差Decode 误改成 sparse_mode=0滑窗层 Prefill+Decode 统一 sparse_mode=4 + band,配 pre_tokens=sliding_window / next_tokens=0
actual_seq_lengths 错误TND 应用 cumsum,BSH 用原始值;框架部署字段名 actual_seq_lengths_cu_q vs actual_seq_lengths_kv参考 model-infer-kvcache skill §2.4
Decode 首步输出为零actual_seq_qlen 为 0Decode 时应为 1 或 cumsum([1,...])
MLA absorb 模式 key≠valuecache_nope 读写不一致FA 中 key 和 value 都传 cache_nope
scale 参数错误FA v1 用 scale,v2 用 softmax_scale确认参数名与版本匹配
5.3 量化相关
问题根因修复方案
W8A8 精度从某层开始放大dequant_scale 与权重不匹配检查 per-channel/per-tensor scale
W8A8C8 KVCache 精度差KV 缓存量化精度损失检查 KV 量化 scale;考虑 BF16 KV
antiquant_mode 不匹配FA v1/v2 量化接口不同v1 用 antiquant_,v2 用 dequant_
5.4 Prefill/Decode 一致性
问题根因修复方案
Prefill 不走 KVCache 写入条件分支逻辑错误确保 Prefill 也执行写入算子
Decode 使用了与路径不符的 FA 参数阶段分支判断或路径分类错误阶段分支取自 forward_metadata.is_prefill;按路径分类配 sparse_mode / atten_mask(标准 LLM TND PA 不分阶段统一配置;MLA absorb 才显式分支 Decode 切到 0+None)
切换阶段时 kv_len 未更新Prefill 后未执行 kv_len += seq_len在 Prefill→Decode 切换时由 Runner 层(独立部署)或 ExecutionEngine(框架部署)更新
MLA absorb Decode 误传 atten_mask切到 sparse_mode=0 后没把 mask 设 NoneMLA absorb Decode 同时设 sparse_mode=0 + atten_mask=None

附录 F:FA 入参配置参考

表格供快速验证清单引用,完整校验代码见 references/fa_debug_utils.md,可在 FA 调用前插入 debug_fa_all_params() 一键检查。
F.1 atten_mask 与 sparse_mode 联合校验
sparse_mode含义atten_mask 要求适用路径常见错误
0defaultMask可选,通常 NoneMLA absorb Decode(q_len=1)误把标准 LLM TND PA Decode 也切到此路径
1allMask必传 (Q_S, KV_S)特殊忘记传 mask
2leftUpCausal不推荐——
3rightDownCausal必传 (2048, 2048) 下三角标准 LLM TND PA(Prefill+Decode 统一)、MLA absorb Prefillmask 不是下三角;MLA absorb Decode 误用
4band(滑窗)必传 (2048, 2048)滑窗层 Prefill+Decode 统一pre_tokens/next_tokens 错误;FA v1 + BSH + Q_S=1 Decode 路径 op 内部忽略
F.2 FA v1 vs v2 关键参数名映射
功能FA v1FA v2易错点
缩放系数scalesoftmax_scale默认 1.0,传错名精度崩溃
Q head 数num_headsnum_query_heads传错名默认 1
Q 长度actual_seq_lengthsactual_seq_qlen名称完全不同
KV 长度actual_seq_lengths_kvactual_seq_kvlen名称完全不同
KV 量化antiquant_scale/offsetdequant_scale_key/valuev2 分离 key/value
F.3 input_layout 与 tensor shape 匹配
layoutQ 维度K/V 维度适用场景
TND ★3D [T, N, D]3D [T, N, D]框架部署 PA 标准 LLM 默认推荐,T = packed tokens
TND_NTD ★3D [T, N, D]3D [N, T, D]框架部署 PA + MLA absorb 默认推荐,KV 是 NZ 格式
BSH3D [B, S, H*D]3D [B, S, H*D]migrator 骨架 / 独立部署连续缓存(非 PA)
BNSD4D [B, N, S, D]4D [B, N, S, D]非 PA,扩散模型
BSND_NBSD4D [B, S, N, D]4D [N, B, S, D]KVP 长序列场景(普通 PA 模型走 TND/TND_NTD)
★ 标注的 TND / TND_NTD 是框架部署默认推荐 layout(详见 model-infer-kvcache §2.7)。PA 模式下 KV 按 block_table 索引,物理存储 shape [total_blocks, block_size, num_kv_heads, head_dim],FA 调用时 view 为 [bn, bs, num_head*dim]。
F.4 actual_seq_lengths 构造
layoutactual_seq_qlenactual_seq_kvlen
TND累积和 cumsum([s1, s2, ...])累积和
BSH / BNSD原始值 [s1, s2, ...]原始值

Decode 时 actual_seq_qlen 每个值通常为 1(MTP 场景除外)。

F.5 inner_precise 行无效
值精度模式行无效修正适用场景
0高精度否默认
1高性能否精度要求不高
2高精度是Prefill + 自定义 mask 有全遮蔽行
3高性能是同上但允许精度损失
F.6 MLA rope 约束
  • query_rope 和 key_rope 必须同时传或同时不传
  • rope D 必须为 64,query D 仅支持 512 或 128
  • D=512 时仅支持 sparse_mode 为 0、3、4

精度调试报告模板

markdown
## 精度调试报告
### 问题概要
-症状:{描述}
-定位阶段:{Prefill / Decode / 两者}
-定位模块:{KVCache 写入 / FA 计算 / 量化参数 / ...}
### 根因分析
-原因:{具体原因}
-影响范围:{受影响的层/模块}
### 修复措施
| 修改文件 | 修改内容 | 修改原因 |
|---------|---------|---------|
| {file} | {change} | {reason} |
### 修复验证
-精度对比:{通过/未通过,max_rel_diff, cosine_similarity}
-输出一致性:{token 序列对比结果}
### 遗留风险
-{如有,列出可能的后续风险}

其他已知精度问题

以下问题来自本仓已适配模型的调试经验,不属于 KVCache/FA 范畴但会导致精度异常。
问题症状根因修复
MoE 专家权重未加载MoE 输出全零或接近零,cosine~0.4-0.8Checkpoint 用 packed tensor 但 load_weights 用 per-expert mapping,权重未正确拷贝添加 packed expert weight loader,按 EP rank 切片后 copy_ 到参数
Zero expert 处理错误MoE 输出偏差或切换路由算子后精度骤降至 ~40-50%零专家 identity 贡献公式错(应用 original_input 而非 MoE 输出),或路由算子 v1 无 active_expert_range 导致零专家 ID 污染 token 排列路由前用 mask 分离零专家,路由后加回 original_input * weight 的 identity 贡献
DP+EP token 不同步 → NaNDecode 若干步后出现 NaN,之后全部 NaNEP all_to_all 有浮点非确定性,DP 各 rank token 选择分叉 → KV cache 累积偏差每步 Decode 后 dist.broadcast(next_token, src=0) 强制所有 DP rank 使用相同 token
跳过训练组件的 scale 缺失输出语义正确但严重重复/退化模型训练时有额外组件,跳过后 embedding 幅度不匹配保留训练时的 normalization factor

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/mcgatom/codex-cannbot/model-infer-precision-debug/badge)](https://verified-skill.com/skills/mcgatom/codex-cannbot/model-infer-precision-debug)

Something wrong with this skill or its page? Tell us.