name: pypto-precision-debug description: PyPTO 算子精度问题排查技能。专注于用户代码层面的语法逻辑检查和规避方法尝试。当算子精度验证失败、输出结果异常、计算错误、数值偏差、或任何与精度相关的问题时使用此技能。

PyPTO 算子精度问题排查技能

此技能专注于用户代码层面的精度问题排查,提供语法逻辑检查和规避方法。

核心定位

⭐ 职责范围

本技能负责

  • 用户代码语法逻辑检查
  • 提供规避方法和工具
  • 尝试各种可能的解决方案

本技能不负责

  • 底层框架代码分析
  • 深层根因定位
  • 框架 Bug 确认

结论判断

  • 如果规避方法有效 → 提供解决方案
  • 如果规避方法无效 → 报告可能是底层框架层面问题

常见规避方法速查表

⚠️ 遇到精度问题时,按优先级顺序逐一尝试以下规避方法。优先级 1 为默认推荐方案。

优先级 问题现象 规避方法 代码示例 原因说明
1 ★推荐 未使用 pypto.frontend.jit 使用 pypto.frontend.jit @pypto.frontend.jit pypto.frontend.jit 是 PyPTO 推荐写法,可避免多种已知问题
2 view + reshape 精度异常 view 后避免 inplace=True(单独 reshape 可安全使用 inplace=True pypto.reshape(tensor_view, shape, inplace=False) view 后 inplace=True 会错误修改内存地址
3 循环展开后精度异常 unroll_list=[1] pypto.loop(range(n), unroll_list=[1]) 关闭循环展开,规避 RegisterCopy pass 的寄存器拷贝 bug
4 嵌套循环精度异常 submit_before_loop=True pypto.loop(range(m), submit_before_loop=True) 确保子循环正确提交,避免并行执行时的内存覆盖
5 特定 shape 精度异常 调整 shape 避免尾轴为 1,避免非整除 特定 shape 可能触发 Pass 推导边界情况,导致 valid_shape 错误
6 编译器优化异常 +0.0 技巧 result = compute(...) + 0.0 阻止编译器过度优化,保留计算操作完整性
7 未初始化 Tensor 使用 pypto.zeros() output = pypto.zeros(shape, dtype) pypto.Tensor 创建后是未初始化随机值,使用 zeros 初始化
8 view 未传 valid_shape 添加 valid_shape pypto.view(tensor, shape, valid_shape=actual_size) 动态数据范围最后一块可能小于固定块大小

⭐ 重要提示:使用标准前端装饰器 pypto.frontend.jit

PyPTO 算子开发必须使用 pypto.frontend.jit

pypto.frontend.jit 是 PyPTO 推荐的前端写法,使用此写法可避免多种已知问题。

推荐写法

# 使用 pypto.frontend.jit
@pypto.frontend.jit
def my_kernel(
    input_tensor: pypto.Tensor(shape, pypto.DT_FP32),
    output_tensor: pypto.Tensor(shape, pypto.DT_FP32),
):
    ...

排查决策树

精度问题
    │
    ├─ 步骤 0:前端写法检查
    │   └─ 确认使用 pypto.frontend.jit
    │
    ├─ 步骤 1:用户代码语法检查
    │   ├─ 数据类型正确?
    │   ├─ shape 定义正确?
    │   └─ valid_shape 配置正确?
    │
    ├─ 步骤 2:快速规避方法尝试
    │   ├─ 避免 view + reshape inplace=True
    │   ├─ unroll_list=[1]
    │   ├─ submit_before_loop=True
    │   ├─ +0.0 技巧
    │   ├─ 调整 shape
    │   ├─ 初始化 Tensor(pypto.zeros())
    │   └─ 添加 valid_shape 参数
    │
    ├─ 步骤 3:二分定位(如需要)
    │
    └─ 步骤 4:结论判断
        ├─ 规避方法有效 ──▶ 提供解决方案
        └─ 规避方法无效 ──▶ 报告可能是框架问题

完整工作流程

步骤 0:检查前端写法

⚠️ 最高优先级:首先确认用户使用了正确的前端写法!

检查内容:查看用户代码中的装饰器是否为 pypto.frontend.jit

依据参考

如果用户未使用 pypto.frontend.jit

  1. 立即建议用户使用 pypto.frontend.jit
  2. 向用户展示正确写法
# ✅ 正确写法
@pypto.frontend.jit
def my_kernel(
    input_tensor: pypto.Tensor(shape, pypto.DT_FP32),
    output_tensor: pypto.Tensor(shape, pypto.DT_FP32),
):
    ...
  1. 重新运行测试验证精度

如果问题解决:结束排查,建议用户使用 pypto.frontend.jit

如果问题未解决:继续下一步

阶段总结

## 步骤 0 总结:前端写法检查

### 检查结果
- 是否使用 pypto.frontend.jit:[是 / 否]

### 结论
- [问题已解决 / 需要继续排查]

步骤 1:用户代码语法检查

⚠️ 重要:先检查用户代码逻辑是否正确,再尝试规避方法。

1.1 数据类型检查

检查项

  • 输入输出数据类型是否一致
  • 中间计算是否需要更高精度
  • 是否存在隐式类型转换

依据参考:通用编程最佳实践。注意:此检查项属于数值计算通用检查方法。

常见问题

问题 现象 解决方法
FP16 精度损失 大数值计算误差 使用 FP32 或调整计算顺序
类型不匹配 计算结果异常 确保类型一致

1.2 Shape 定义检查

检查项

  • shape 是否正确定义
  • 动态轴是否正确标记

依据参考:通用编程最佳实践。注意:此检查项属于张量编程通用检查方法。

常见问题

问题 现象 解决方法
shape 与实际数据不匹配 越界或数据截断 检查 shape 定义
动态轴标记错误 编译或运行时错误 检查动态轴定义

1.3 valid_shape 配置检查

检查项

  • view/reshape 时 valid_shape 参数是否正确
  • 动态 shape 场景下 valid_shape 表达式是否正确

依据参考

示例

# ✅ 正确:view 时直接传入 valid_shape 参数
tensor_view = pypto.view(tensor, shape=[4, 4], offsets=[0, 0], valid_shape=[2, 4])

# ✅ 正确:reshape 时直接传入 valid_shape 参数
tensor_reshaped = pypto.reshape(tensor, new_shape, valid_shape=valid_shape_expr)

常见问题

问题 现象 解决方法
valid_shape 未正确设置 边界数据处理错误 在 view/reshape 时正确传入 valid_shape 参数
valid_shape 与实际数据不匹配 数据截断或越界 确保 valid_shape 与实际有效数据大小一致

阶段总结

## 步骤 1 总结:用户代码语法检查

### 检查结果
- 数据类型检查:[正常/异常 - 描述问题]
- Shape 定义检查:[正常/异常 - 描述问题]
- valid_shape 配置检查:[正常/异常 - 描述问题]

### 发现的问题
1. [问题描述1]
2. [问题描述2]
...

### 修复建议
1. [修复建议1]
2. [修复建议2]
...

### 结论
- [问题已解决 / 需要继续排查]

步骤 2:快速规避方法尝试

⚠️ 重要:以下规避方法按优先级逐一尝试,记录每种方法的效果。

2.1 避免 view + reshape inplace=True

适用场景pypto.view 后再做 pypto.reshape(inplace=True) 导致精度严重偏差

问题现象:精度严重偏差(96%+ 元素超容差)

操作

# ❌ 避免写法
tensor_view = pypto.view(tensor, new_shape, ...)
result = pypto.reshape(tensor_view, final_shape, inplace=True)  # 精度严重偏差

# ✅ 推荐写法
tensor_view = pypto.view(tensor, new_shape, ...)
result = pypto.reshape(tensor_view, final_shape, inplace=False)  # 精度正确

判断:问题是否解决

依据参考:Issue #343 - pypto.view 后再做 pypto.reshape(inplace=True) 时,内存地址或元数据处理错误,inplace=True 的 reshape 试图在原 tensor 上就地修改,但 view 的元数据(offset、valid_shape)未被正确传播,导致 reshape 结果指向错误的内存区域。

2.2 尝试 unroll_list=[1]

适用场景:循环展开后精度异常

操作

# 在循环中添加 unroll_list=[1]
for i in pypto.loop(range(n), unroll_list=[1]):
    ...

判断:问题是否解决

依据参考:Issue #223, #341 - RegisterCopy pass 在处理 unroll 场景时,对 tensor 的寄存器拷贝逻辑存在 bug,某些 unroll 配置下 tensor 的 Copy 路径选择错误,导致数据写入位置偏移。设置 unroll_list=[1] 可关闭循环展开,规避此问题。

2.3 尝试 submit_before_loop=True

适用场景:嵌套循环精度异常

操作

# 在子循环中添加 submit_before_loop=True
for i in pypto.loop(range(n)):
    for j in pypto.loop(range(m), submit_before_loop=True):
        ...

判断:问题是否解决

依据参考docs/api/controlflow/pypto-loop.md - submit_before_loop 参数用于控制嵌套循环的调度行为,确保子循环在父循环迭代前正确提交,避免并行执行时的内存覆盖问题。

2.4 尝试 +0.0 技巧

适用场景:编译器优化导致精度异常

操作

# 在计算结果上添加 + 0.0
result = compute(...) + 0.0

判断:问题是否解决

依据参考:编译器优化 pass 在某些场景下会错误地消除或重排序操作,添加 +0.0 可以阻止过度优化,保留计算操作的完整性。

2.5 尝试调整 shape

适用场景:特定 shape 精度异常

操作

  • 调整 tensor shape,避免尾轴为 1
  • 避免非整除情况
  • 尝试不同的 shape 组合

判断:问题是否解决

依据参考:Issue #498, #787 - 特定 shape(如尾轴为 1、非整除)可能触发 Pass 推导的边界情况,导致 valid_shape 传播错误或 buffer 越界。调整 shape 可规避这些边界场景。

2.6 初始化 Tensor

适用场景:输出 tensor 在写入前被读取,导致未初始化随机值参与计算

问题现象:输出包含随机异常值,每次运行结果不一致

操作

# 使用 pypto.zeros() 创建并初始化为全 0
output = pypto.zeros(shape, dtype)

判断:问题是否解决

依据参考pypto.Tensor 创建后内存为未初始化状态,若存在"先读后写"路径(如循环体中 read-modify-write),未初始化的随机值会混入计算结果。应使用 pypto.zeros() 创建并初始化为全 0 的 Tensor。

2.7 添加 valid_shape 参数

适用场景:动态数据范围最后一块小于固定块大小,导致 view/reshape 后数据越界

问题现象:特定 shape 下精度异常,尾块数据不正确

操作

# view/reshape 时传入 valid_shape 参数
tensor_view = pypto.view(tensor, shape, valid_shape=actual_size)
tensor_reshaped = pypto.reshape(tensor, new_shape, valid_shape=actual_size)

判断:问题是否解决

依据参考:动态 shape 场景下,最后一块可能小于固定块大小。valid_shape 参数告知框架实际有效数据范围,避免读取越界数据。

阶段总结

## 步骤 2 总结:快速规避方法尝试

### 尝试的规避方法及结果
| 方法 | 是否尝试 | 是否有效 | 备注 |
|-----|---------|---------|------|
| 避免 view + reshape inplace=True | [是/否] | [有效/无效] | [描述] |
| unroll_list=[1] | [是/否] | [有效/无效] | [描述] |
| submit_before_loop=True | [是/否] | [有效/无效] | [描述] |
| +0.0 技巧 | [是/否] | [有效/无效] | [描述] |
| 调整 shape | [是/否] | [有效/无效] | [描述] |
| 初始化 Tensor | [是/否] | [有效/无效] | [描述] |
| 添加 valid_shape | [是/否] | [有效/无效] | [描述] |

### 有效的规避方法
[如果有,列出有效的方法]

### 结论
- [问题已解决 / 需要继续排查(二分定位)]

步骤 3:二分定位(如需要)

转入标准:当步骤 2 所有 7 种规避方法均尝试且无效时,进入此步骤。

如果上述方法无法定位问题,使用 pypto-precision-compare skill 查找定位具体问题 op。

阶段总结

## 步骤 3 总结:二分定位

### 二分定位结果
- 是否执行二分定位:[是/否]
- 定位到的问题 op:[op 名称/未定位到]
- 问题代码位置:[文件名:行号]

### 问题分析
[描述定位到的问题及可能原因]

### 结论
- [已定位到问题 / 未定位到问题]

步骤 4:结论判断

情况 A:规避方法有效

输出

## 排查结论

### 问题类型
[描述问题类型]

### 有效的规避方法
[描述有效的规避方法]

### 解决方案
[提供具体的代码修改建议]

### 注意事项
[使用规避方法时的注意事项]

情况 B:规避方法无效

输出

## 排查结论

### 问题现象
[描述问题现象]

### 已尝试的规避方法
1. [方法1] - 无效
2. [方法2] - 无效
3. [方法3] - 无效
...

### 结论
经过多种规避方法尝试,问题仍未解决。**判定前提**:步骤 0-2 全部尝试完毕 + 代码审查无逻辑错误 + 步骤 3 已执行。**可能是底层框架层面的问题**

检查清单

使用此 skill 时,确保:

  • 步骤 0:检查前端写法(最高优先级)

    • 确认使用 pypto.frontend.jit
  • 步骤 1:用户代码语法检查

    • 数据类型

    • Shape 定义

    • valid_shape 配置

    • 步骤 2:快速规避方法尝试

    • 避免 view + reshape inplace=True

    • unroll_list=[1]

    • submit_before_loop=True

    • +0.0 技巧

    • 调整 shape

    • 初始化 Tensor

    • 添加 valid_shape

  • 步骤 3:二分定位(如需要)

  • 步骤 4:结论判断

    • 规避方法有效 → 提供解决方案
    • 规避方法无效 → 报告可能是框架问题

参考资料

文档资料

文档 路径 说明
已知问题文档 docs/tutorials/appendix/issue.md 常见问题及解决方案
循环开发指南 docs/tutorials/development/loops.md loop 使用方法

API 文档

API 文档路径 说明
pypto.loop docs/api/controlflow/pypto-loop.md 循环接口,含 submit_before_loop 参数
pypto.loop_unroll docs/api/controlflow/pypto-loop_unroll.md 循环展开接口,含 unroll_list 参数
pypto.tensor docs/tutorials/development/tensor_creation.md Tensor 创建方法
pypto.reshape docs/api/operation/pypto-reshape.md reshape 操作,含 inplace 参数
pypto.view docs/api/operation/pypto-view.md view 操作
valid_shape docs/tutorials/development/tensor_operation.md Tensor 操作方法,含 valid_shape 说明