ascend-ai-coding/awesome-ascend-skills/ascendc-precision-debug

Claude Code and agent skill by ascend-ai-coding/awesome-ascend-skills

Trust tier 3
  • community
Source check pending

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

Ascend C 算子精度调试技能,提供精度问题诊断和解决方法。触发:输出异常(全为0、随机值、未初始化)、精度验证失败(rtol/atol

Install

npx vskill@latest install ascend-ai-coding/awesome-ascend-skills/ascendc-precision-debug

SKILL.md

Ascend C 算子精度调试

核心理念

精度调试 = 理解 + 分析 + 定位 + 修复
  1. 理解数据类型限制:FP16 约 3-4 位有效数字,FP32 约 6-7 位。
  2. 识别数值稳定性问题:大数吃小数、灾难性抵消。
  3. 掌握科学调试方法:从最小复现到根因分析。

使用时机

适用:精度验证失败(rtol/atol 不达标)、输出全为0或随机值、FP16差于FP32、特定数值范围误差大、流水线同步问题、DataCopy对齐问题。


调试前置要求 ⭐⭐⭐

进入调试前必须完成以下三步
1. 固定最小可复现用例
项目说明示例
Shapetensor 形状{8, 16}
Dtype数据类型float16
固定值具体数值[1.0, 2.0, -0.5, ...]

选择原则:优先简单 → 优先32字节对齐 → 优先FP32 → 覆盖边界值

💡 推荐实践:调试时建议在至少两个 dtype(如 FP16 和 FP32)上用同一 shape + 同一数据验证。如果一种 dtype 通过另一种失败,可按下方对应的诊断模式快速缩小范围。

2. 检索 asc-devkit ⭐
禁止凭直觉修改代码

检索顺序:

  1. 搜索 asc-devkit/examples/ 查找类似算子。
  2. 查看 asc-devkit/docs/api/context/ API 文档。
  3. 对比官方实现与当前实现。
3. 清理缓存和临时文件
bash
rm -rf build input output
mkdir -p build/input build/output

快速决策树

[前置检查] 已固定用例?已检索API?已清理缓存?
│
└─ 否 → 先完成前置步骤
└─ 是 → 继续
│
├─ [第0步] ⭐ 代码修改后输出完全不变?
│ ├─ 是 → 清理 build/ 和 kernel_cache 后重试
│ └─ 否 → 继续
│
├─ [第0.5步] ⭐ 多 dtype 交叉验证
│ ├─ FP32通过但FP16/BF16失败 → 精度不足,见下方诊断模式
│ ├─ BF16通过但FP16/FP32失败 → API fallback 路径差异 或 精度阈值差异,见下方诊断模式
│ └─ 全部通过/全部失败 → 继续
│
├─ [第一步] 排查数据搬运 ⭐⭐⭐
│ ├─ 输出是否全为 0 或随机错误?
│ │ ├─ 是 → 检查流水线同步(EnQue / DeQue)⭐⭐⭐
│ │ │ └─ DataCopy 后直接计算?→ 添加 EnQue/DeQue
│ │ │ └─ 临时验证:加 PipeBarrier,若正确则确认同步问题
│ │ ├─ 检查 DataCopy 是否 32 字节对齐
│ │ │ └─ 非对齐 → 改用 DataCopyPad
│ │ └─ 检查是否使用 GlobalTensor.SetValue
│ │ └─ 是 → 改用 LocalTensor.SetValue + DataCopyPad 搬出到 GM
│ └─ 验证:用 "CopyIn → CopyOut" 测试搬运
│
├─ [第二步] 对比分析
│ └─ 对比官方示例与当前实现 → 发现差异
│
└─ [第三步] 诊断问题类型
├─ 所有结果都差 → 公式/常量/API选择
├─ 个别值错误 → 边界条件/除零/溢出
└─ 误差整体偏大 → FP16精度不足 → 尝试FP32中间计算

症状-原因速查表

症状可能原因诊断方向
输出全为 0 或随机错误流水线同步缺失 / DataCopy 非对齐 / GlobalTensor.SetValue检查 EnQue / DeQue、数据对齐、改用 LocalTensor.SetValue + DataCopyPad ⭐⭐⭐
sum=0, max_err=输入级别输出没写出检查输出队列类型(VECIN vs VECOUT)
sum=0, max_err≈0输出全0/未初始化检查 UB 溢出、buffer 分配
特定参数范围失败阈值/边界错误验证阈值计算、检查分支条件
非对齐数据失败DataCopy 对齐问题改用 DataCopyPad
FP16 差但 FP32 好精度不足中间计算用 FP32
Cast 后数据错误RoundMode 错误half → float用CAST_NONE,float → half用CAST_ROUND
BF16 通过但 FP16/FP32 失败(1) 部分 API 不支持 BF16,BF16 走了更简单的 fallback 路径反而正确;(2) BF16 与 FP16/FP32 精度特性不同(BF16 mantissa 7bit vs FP16 10bit),精度阈值或溢出行为差异先排查 API fallback 分支差异,再检查精度阈值(rtol/atol)是否适配各 dtype
FP32 通过但 FP16/BF16 失败半精度中间计算精度不足升精度:Cast → FP32 计算 → Cast 回半精度
修改代码后输出完全不变二进制未更新 / 编译器缓存清理 build/ 和 $HOME/atc_data/kernel_cache/ 后重试
诊断模式:"FP32 通过但 FP16/BF16 失败"

这是最常见的精度诊断信号:FP16/BF16 在 Ascend C 中通常共享相同的 Cast-to-FP32 计算路径(if constexpr (std::is_same_v<T, bfloat16_t> || std::is_same_v<T, half>)),FP32 通过说明核心算法正确,问题在半精度转换环节。

确认: FP32通过,FP16/BF16失败
│
├─ 检查中间计算精度
│ ├─ FP16/BF16 Cast→FP32 计算路径是否正确?
│ ├─ 是否有未升精度的中间运算(如直接 Add<half>)?
│ └─ 验证:将 FP16 路径的中间计算全部用 FP32,观察结果
│
├─ 检查 Cast RoundMode
│ ├─ half→float 应使用 CAST_NONE
│ ├─ float→half 应使用 CAST_ROUND
│ └─ 验证:对比 Cast 前后的数值
│
├─ 检查 Pipeline 同步
│ ├─ FP16/BF16 路径有额外的 Cast 操作,Cast 后是否 EnQue/DeQue?
│ ├─ FP32 路径无 Cast,天然无此同步问题
│ └─ 验证:在 Cast 后加 PipeBarrier,若正确则确认同步问题
│
└─ 检查 Buffer 大小
├─ FP16/BF16 路径需额外 Cast buffer(2× innerDim × sizeof(float))
├─ FP32 路径不需要 Cast buffer
└─ 验证:检查 Tiling 中 castBuf 大小计算
诊断模式:"BF16 通过,但 FP16/FP32 失败"

这是一个有价值的诊断信号,可能由两类原因导致:

原因1:API 不支持导致 fallback 路径差异。部分 Ascend C 算术/归约 API 不支持 BF16,开发者为 BF16 实现更简单的 fallback 路径。BF16 fallback 通过说明逻辑正确,问题出在 FP16/FP32 路径中调用的复杂 API 上。

原因2:精度阈值 / 数值范围差异。BF16 (mantissa 7bit, 指数范围同 FP32) 与 FP16 (mantissa 10bit, 指数范围更小) 精度特性不同:BF16 不易溢出但尾数精度低,FP16 易溢出但尾数精度高。如果验证阈值(rtol / atol)未区分适配,或 FP16 发生溢出而 BF16 没有,就会出现 BF16 通过但 FP16 失败。

确认: BF16通过,FP16/FP32失败
│
├─ [原因1] API fallback 路径差异
│ ├─ 搜索代码中 if constexpr (std::is_same_v<T, bfloat16_t>) 分支
│ ├─ BF16 走的 fallback 路径 vs FP16/FP32 走的主路径,差异在哪里?
│ ├─ 列出 FP16 / FP32 路径中使用但 BF16 路径未使用的 API
│ ├─ 逐个验证差异 API 的参数(mask、repeatTime、stride)
│ └─ 临时将 FP16 路径改为与 BF16 相同的 fallback 实现,观察是否通过
│
├─ [原因2] 精度阈值 / 数值范围差异
│ ├─ FP16 是否溢出?(FP16 max ≈ 65504,BF16 指数范围同 FP32)
│ ├─ 验证阈值(rtol/atol)是否按 dtype 区分?
│ │ ├─ BF16: rtol=1e-2 级别(mantissa 仅 7bit)
│ │ └─ FP16: rtol=1e-3 级别(mantissa 10bit)
│ └─ 检查中间计算是否因 FP16 的更高精度要求暴露了算法缺陷
│
└─ 交叉验证
├─ 检查 asc-devkit 文档确认相关 API 是否支持 BF16
├─ 如果 API 不支持 BF16 → 优先按原因1排查
└─ 如果 API 支持 BF16(BF16/FP16 走相同路径)→ 优先按原因2排查

常见陷阱速查

陷阱症状解决方案
流水线同步缺失输出全0或随机错误DataCopy 后必须 EnQue/DeQue 同步 ⭐⭐⭐
DataCopy 非对齐小规模数据全0/异常使用 DataCopyPad ⭐⭐⭐
GlobalTensor.SetValue输出全为0改用 LocalTensor.SetValue + DataCopyPad 搬出到 GM ⭐⭐⭐
Cast RoundModeCast后数据混乱half→float用CAST_NONE,float→half用CAST_ROUND ⭐
FP16 精度不足简单计算也有误差关键中间值用 FP32
exp/log 溢出出现 Inf 或 NaN先减最大值再计算
减法抵消a≈b 时 a-b 误差大使用数值稳定等价公式
Reduce 误差Reduce 结果比逐元素误差大使用 FP32 累加器
除零风险NaN 或异常大值添加 epsilon 保护
流水线同步调试

核心问题:DataCopy / DataCopyPad 是异步 DMA 操作,直接在搬运后的数据上做 Vector 计算可能读到未完成的数据!

cpp
// ❌ 错误:AllocTensor 后直接用
LocalTensor<T> x = inQueue.AllocTensor<T>();
DataCopy(x, gm, size);
Compute(x); // 错!可能读到未完成搬运的数据
// ✅ 正确:DeQue 后再计算
LocalTensor<T> x = inQueue.AllocTensor<T>();
DataCopy(x, gm, size);
inQueue.EnQue(x);
LocalTensor<T> xIn = inQueue.DeQue<T>(); // 等待搬运完成
Compute(xIn);

临时调试方法:

cpp
DataCopy(x, gm, size);
PipeBarrier<PIPE_ALL>(); // 临时加,如果结果正确说明是同步问题
Compute(x);

如果 PipeBarrier 能解决问题,说明是同步问题 → 修复方案:改为 EnQue/DeQue 机制

误区正确理解
AllocTensor 后数据就可用AllocTensor 只分配内存,不等待搬运
DataCopy 是同步的DataCopy 是异步 DMA,立即返回
不用 EnQue/DeQue 也能正常工作必须用 EnQue/DeQue 或 PipeBarrier 同步
PipeBarrier 性能好PipeBarrier 是全流水线停顿,性能差

详细说明见 references/common-traps.md


调试策略层级

调试方法
│
├─ 快速方法(优先尝试,≤7次)
│ ├─ 误差分布分析 → 识别误差模式
│ ├─ Printf 特定位置 → 缩小范围
│ └─ 常见陷阱排查 → 对症下药
│
└─ 二分调试(保底手段)
└─ 快速方法尝试≥7次或方法穷尽时立即切换
重要原则:不要盲目试错超过 7 次

问题定位方法

1. 对比法(与工作的代码对比)

找到正常工作的代码,逐行对比差异

2. 边界二分法

记录通过/失败的临界点,分析分支选择

3. 数值验证法

不要相信估算公式,用代码计算实际值

4. Buffer 调试要点
问题表现解决方案
VECIN 用于输出输出等于输入输出必须用 VECOUT 队列
Double Buffer 漏算阈值错误计算阈值时 ×2

详细定位流程见 references/diagnosis-workflow.md


精度标准来源优先级

  1. 优先级1:算子开发 Plan 中明确的精度要求
  2. 优先级2:华为昇腾官方精度标准文档
  3. 优先级3:本 Skill 默认值(仅作兜底)
数据类型rtolatol
FP161e-31e-4
FP321e-51e-6
INT-0

Agent 使用指南

调试计数规则
计数器 = 0
每次尝试快速方法(误差分析/Printf/陷阱排查)→ 计数器+1
当 计数器 >= 7 或 快速方法穷尽 → 立即切换二分调试
💡 经验建议:如果多次尝试未取得进展(失败用例数量未减少),建议:
1. 检查是否清理了编译缓存(rm -rf build/ $HOME/atc_data/kernel_cache/)
2. 验证修改后二进制 sha256 是否确实改变
3. 切换到完全不同的调试策略(如二分法降级到最小工作路径)
调试总结要求

每步调试成功后必须形成总结:

  • 文档描述不清晰的地方
  • 需要改进的地方及推荐方案
  • 给 Agent 造成困扰的点
  • 调试过程记录

总结模板:references/debug-summary-template.md

检查清单

调试阶段:

  • [ ] 已固定最小可复现用例
  • [ ] 已检索 asc-devkit 确认 API 用法 ⭐
  • [ ] 已清理缓存和临时文件
  • [ ] 已排查流水线同步问题(DataCopy 后是否 EnQue/DeQue)⭐⭐⭐
  • [ ] 已排查输出全为 0 问题(DataCopy 对齐 / GlobalTensor.SetValue → LocalTensor.SetValue + DataCopyPad)⭐⭐⭐
  • [ ] 对比官方示例与当前实现
  • [ ] 尝试次数 < 7
  • [ ] 达到阈值立即切换二分调试

参考资料

工作流程
问题诊断
调试工具
实战案例

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

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

Source

Popularity

Repository stars
173
Repository forks
60
7-day trend score
26

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 25 Sep 2026, a month ago.

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/ascend-ai-coding/awesome-ascend-skills/ascendc-precision-debug/badge)](https://verified-skill.com/skills/ascend-ai-coding/awesome-ascend-skills/ascendc-precision-debug)

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