CANN/cannbot-skills踩坑经验
踩坑经验【免费下载链接】cannbot-skillsCANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体本仓库为其提供可复用的 Skills 模块。项目地址: https://gitcode.com/cann/cannbot-skills先探测 API再写测试禁止凭文档或直觉猜测 API 名称和签名。编写测试前必须执行探测python -c import torch_npu; print(hasattr(torch_npu, npu_xxx)) python -c import torch, torch_npu; torch_npu.npu_xxx(torch.randn(1,2).npu())在代码中用hasattr守护HAS_NPU_OP hasattr(torch_npu, npu_xxx) and torch.npu.is_available() if not HAS_NPU_OP: pytest.skip(npu_xxx not available)Golden 函数的唯一来源是 aclnn 文档「计算公式」只读算子docs/aclnn*.md文件中的「计算公式」这一节通常紧跟在接口功能之后以$$包裹的公式不读同一文档的其他节函数原型、参数说明、示例代码等不推不从 kernel 源码反推公式——kernel 是参考实现不是定义公式中每个变量的含义必须从公式本身推断不需要读参数说明表输出-公式映射表编写 reference 前必须为每个输出 tensor 显式标注其对应的公式表达式。格式以注释形式声明在 reference 函数上方# 输出-公式映射 # - {output_name_1} {公式表达式} ← 来自公式 {来源小节} # - {output_name_2} {公式表达式} ← 来自公式 {来源小节} # - {output_name_3} {公式表达式} ← 来自公式 {来源小节}未显式定义经数值验证确认如果公式节未显式给出某个输出的表达式必须通过数值交叉验证见第 6 条确定禁止猜测。数值语义验证当公式节未显式定义某个输出的计算式时用一个小 case 在 NPU 上运行列出所有候选表达式并逐个计算 diff选择 diff 最小的作为正确语义。将验证结论写入输出-公式映射表注释中。Reference 必须用真实 NPU 输出交叉验证先手动跑一个小 case 对比 NPU 输出和 reference 输出确认一致后再批量生成测试。关注点输出 shapeNPU 返回的 shape 是否与 reference 一致尤其注意广播、未 expand 的中间结果等输出 dtype每个输出的实际 dtype 是否与预期一致尤其注意混合精度场景下中间输出与主输出 dtype 不同输出数量API 实际返回几个值可能不等于接口文档描述输出语义每个输出 tensor 的数值是否与输出-公式映射表中声明的表达式一致。禁止只检查 shape/dtype 而跳过数值语义验证。禁止假 PASS — 没验证就不能报通过# ✅ 正确NPU 不可用时 skip或做了实质验证才 report pass if not HAS_NPU_OP: pytest.skip(NPU not available) # ... NPU 对比 ... # ❌ 错误NPU 对比放在 if 里else 分支只做了 CPU 属性检查就放行 if HAS_NPU_OP: torch.testing.assert_close(npu_out, ref_out) # 没有 else → CPU 上跑了个 assert shape expected 就 PASSED假 PASS输出含 inf/nan 时比较必须用 equal_nanTrue边界值输入extreme取 dtype 最大值或多步算子会导致中间计算溢出输出包含 inf/nan这是正常测试路径。# ❌ 错误默认 equal_nanFalsenan ! nan 必然失败 torch.testing.assert_close(npu_out.cpu(), ref_out, rtolrtol, atolatol) # ❌ 错误放任 FAILED 不处理门禁会拦截 torch.testing.assert_close(npu_out.cpu(), ref_out, rtolrtol, atolatol, equal_nanTrue) # ❌ 错误降低精度标准放行见铁律 torch.testing.assert_close(npu_out.cpu(), ref_out, rtol1.0, atol1.0)正确写法已在 01-code-templates.md「断言」节给出try/except equal_nanTrue pytest.xfail。可变输出数量的算子 — 全量解包按模式验证部分算子的接口支持多种输出模式如根据可选输出参数是否为 None 决定返回不同数量的输出。torch_npu Python API 通常固定返回所有输出 tensor。禁止做法因为当前模式不需要某个输出就跳过整个用例。# ❌ 错误某个模式下不需要某输出直接跳过 if mode ! full_mode: pytest.skip(mode not supported)正确做法始终用全量变量承接返回值然后根据模式只验证该模式应有的输出。# ✅ 正确全量解包按模式验证 outputs npu_op(input_1, input_2, ...) npu_out_0 outputs[0] npu_out_1 outputs[1] if len(outputs) 1 else None npu_out_2 outputs[2] if len(outputs) 2 else None # shape/dtype 检查所有模式下都检查的输出 assert npu_out_0.shape expected_shape_0 assert npu_out_0.dtype expected_dtype_0 # 按模式验证对应输出 if should_verify_output_1: assert npu_out_1.shape expected_shape_1 if should_verify_output_2: validate(npu_out_2, ref_out_2)原则API 返回几个 tensor 就解包几个禁止丢弃或跳过Reference 始终按最完整模式计算因为底层实际执行的是完整路径不同模式通过控制验证哪些输出来区分而非控制是否执行用例目标0 skipped所有枚举预算都用于实际验证DYNAMIC TensorList 注意事项当 S5_mapping_spec.md 中存在 param_typeDYNAMIC 的 input/output 时需额外注意API 调用DYNAMIC 算子的 Python API 接受list[Tensor]输入返回list[Tensor]输出如torch._foreach_xxx(x_list)返回[Tensor, ...]。禁止对子 tensor 逐个调用 API效率低且语义错误。Reference 实现对 TensorList 输入逐子 tensor 计算返回list[Tensor]# ✅ 正确list comprehension 逐子 tensor 计算 ref_out [reference_fn(t) for t in x_list] # ❌ 错误对 list 调用标量 API ref_out reference_fn(x_list) # TypeError 或语义错误断言嵌套迭代DYNAMIC 输出为list[Tensor]需逐子 tensor 对比见 01-code-templates.md「DYNAMIC 模式」。禁止对 list 整体做assert_close。空子 tensor 安全性空 tensor 变体ID 含_empty后缀的子 tensor shape 含 0 维度如[0, 5]。make_data对空 shape 返回空 tensortorch.randn([0, 5])正常工作。空 case 始终_data_range: normal不会触发with_inf/with_nan的view(-1)[0]越界空 tensor 无元素可索引但view(-1)[0]会抛 IndexError。因此空 tensor 路径不经过with_inf/with_nan分支安全。【免费下载链接】cannbot-skillsCANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体本仓库为其提供可复用的 Skills 模块。项目地址: https://gitcode.com/cann/cannbot-skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考