一键导入
ascendc-precision-debug
Ascend C 算子精度调试技能,提供精度问题诊断和解决方法。触发:输出异常(全为0、随机值、未初始化)、精度验证失败(rtol/atol 不达标)、FP16 精度差于预期、Cast 后数据错误、需要排查流水线同步(EnQue/DeQue)或 DataCopy 对齐问题。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Ascend C 算子精度调试技能,提供精度问题诊断和解决方法。触发:输出异常(全为0、随机值、未初始化)、精度验证失败(rtol/atol 不达标)、FP16 精度差于预期、Cast 后数据错误、需要排查流水线同步(EnQue/DeQue)或 DataCopy 对齐问题。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Profile PyPTO kernels in-core with the Ascend msprof op-simulator — cycle-accurate per-kernel traces. Use when the user wants to profile a built case, inspect kernel timing or instruction streams, or generate MindStudio Insight traces.
Tune cube/matmul tile sizes (row tile, N fragment, K fragment) for a PyPTO kernel — analytic hints, an on-chip buffer constraint model, and an empirical device sweep. Use when optimizing a matmul/cube's throughput, sizing the row / N / K tiles, resolving Mat (L1) / L0C / UB buffer overflows, or trading one tile dim for another.
Locate which pypto commit introduced a precision regression. Only pypto and its corresponding simpler (submodule) are tracked — ptoas and pto-isa versions are not part of the bisect. If the culprit is a simpler submodule bump, performs a second-level bisect within simpler.
Reproduce a reported problem, collect dependency versions, and create a GitHub issue. Use when the user wants to file a bug, request a feature, or create any GitHub issue.
Ascend C 开发资源索引(本地+在线)。提供:(1) 本地 API 文档索引、示例代码映射,(2) 在线文档搜索功能,(3) 资源查找优先级,(4) Explore Agent 使用指南。优先使用本地资源,仅在本地检索不到时使用在线搜索。
Complete git commit workflow including pre-commit checks, staging, message generation, and verification. Use when creating commits or preparing changes for commit.
| name | ascendc-precision-debug |
| description | Ascend C 算子精度调试技能,提供精度问题诊断和解决方法。触发:输出异常(全为0、随机值、未初始化)、精度验证失败(rtol/atol 不达标)、FP16 精度差于预期、Cast 后数据错误、需要排查流水线同步(EnQue/DeQue)或 DataCopy 对齐问题。 |
精度调试 = 理解 + 分析 + 定位 + 修复
适用:精度验证失败(rtol/atol 不达标)、输出全为0或随机值、FP16差于FP32、特定数值范围误差大、流水线同步问题、DataCopy对齐问题
不适用(功能问题):编译错误、运行时错误、逻辑异常
进入调试前必须完成以下三步
| 项目 | 说明 | 示例 |
|---|---|---|
| Shape | tensor 形状 | {8, 16} |
| Dtype | 数据类型 | float16 |
| 固定值 | 具体数值 | [1.0, 2.0, -0.5, ...] |
选择原则:优先简单 → 优先32字节对齐 → 优先FP32 → 覆盖边界值
禁止凭直觉修改代码
检索顺序:
asc-devkit/examples/ 查找类似算子asc-devkit/docs/api/context/ API 文档rm -rf build input output
mkdir -p build/input build/output
[前置检查] 已固定用例?已检索API?已清理缓存?
│
└─ 否 → 先完成前置步骤
└─ 是 → 继续
│
├─ [第一步] 排查数据搬运 ⭐⭐⭐
│ ├─ 输出是否全为 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 分配 |
核心超时/挂起 | Buffer 冲突/死锁 | 检查 Alloc/Free 配对 |
特定参数范围失败 | 阈值/边界错误 | 验证阈值计算、检查分支条件 |
非对齐数据失败 | DataCopy 对齐问题 | 改用 DataCopyPad |
FP16 差但 FP32 好 | 精度不足 | 中间计算用 FP32 |
Cast 后数据错误 | RoundMode 错误 | half→float用CAST_NONE,float→half用CAST_ROUND |
| 陷阱 | 症状 | 解决方案 |
|---|---|---|
| 流水线同步缺失 | 输出全0或随机错误 | DataCopy 后必须 EnQue/DeQue 同步 ⭐⭐⭐ |
| DataCopy 非对齐 | 小规模数据全0/异常 | 使用 DataCopyPad ⭐⭐⭐ |
| GlobalTensor.SetValue | 输出全为0 | 改用 LocalTensor.SetValue + DataCopyPad 搬出到 GM ⭐⭐⭐ |
| Cast RoundMode | Cast后数据混乱 | 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 计算可能读到未完成的数据!
// ❌ 错误: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);
临时调试方法:
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 次
找到正常工作的代码,逐行对比差异
记录通过/失败的临界点,分析分支选择
不要相信估算公式,用代码计算实际值
| 问题 | 表现 | 解决方案 |
|---|---|---|
| VECIN 用于输出 | 输出等于输入 | 输出必须用 VECOUT 队列 |
| Buffer 未释放 | 核心挂起/超时 | 循环内 Alloc 后必须 Free |
| Double Buffer 漏算 | 阈值错误 | 计算阈值时 ×2 |
详细定位流程见 references/diagnosis-workflow.md
| 数据类型 | rtol | atol |
|---|---|---|
| FP16 | 1e-3 | 1e-4 |
| FP32 | 1e-5 | 1e-6 |
| INT | - | 0 |
计数器 = 0
每次尝试快速方法(误差分析/Printf/陷阱排查)→ 计数器+1
当 计数器 >= 7 或 快速方法穷尽 → 立即切换二分调试
每步调试成功后必须形成总结:
总结模板:references/debug-summary-template.md
调试阶段: