| name | external-cannbot-ops-pypto-op-perf-tune |
| description | PyPTO 算子性能分析和自动调优技能。用于对生成及新开发的算子进行性能分析及自动调优,包括算子用例执行及精度校验、性能数据采集及分析、分步骤性能调优和生成性能分析报告。当用户需要分析 PyPTO 算子性能、进行性能调优、生成性能报告时使用此技能。触发词:算子性能调优、性能分析、自动调优、性能优化、泳道图分析。 |
| original-name | pypto-op-perf-tune |
| synced-from | https://gitcode.com/cann/cannbot-skills |
| synced-date | 2026-05-26 |
| synced-commit | ac5bbd2b4cf427d011874e11f8d1e8b1bef66eda |
| license | UNKNOWN |
PyPTO 算子性能分析和自动调优
概述
此技能提供 PyPTO 算子性能调优的完整工作流程,包括精度校验、性能数据采集、性能分析和迭代调优。
核心原则
⚠️⚠️⚠️ 非常重要:所有的调优验证必须上板执行,拒绝理论猜测,凭空捏造!!!
1. 性能调优前提(最高优先级)
⚠️ 非常重要:性能调优必须建立在精度正确的基础上!
⛔ 禁止:没有精度验证通过的记录,绝对禁止进入任何调优步骤!
核心要求:
- ✅ 精度必须通过:首先确保算子精度校验通过,才能进行性能调优
- ✅ 每次验证精度:每次调优修改后,必须重新验证精度(不要怕麻烦!)
- ❌ 精度失败不修复:
- 首轮失败:不进行修复,可以换卡尝试,多次失败让用户确认
- 调优修改导致失败:可以进行简单分析后,如果不能解决,则回退修改,记录失败原因,尝试其他优化方案
- ⚠️ 精度问题是算子实现问题,不是调优能解决的,可以尝试,但不强制解决
详细处理流程:见步骤 1.4(精度校验)和步骤 4.3(迭代调优流程)
2. 迭代优化原则
⚠️ 重要:性能调优是一个循环迭代的过程!
- 修改一处改动点后,立即验证精度
- 精度通过后,立即测试性能
- 不要全部改完再测
- 对比修改前后的性能数据
- 如果性能回退或者执行超时等异常情况,尝试修改,如果不能解决,则回退修改,记录失败,尝试其他方案
- 重复上述过程直到达到目标性能
⚠️ 注意:当长时间无法达到性能目标,或者识别没有调优空间时,可以尝试重新设计算子
3. 留痕可溯原则
⚠️ 重要:性能调优是一个可追溯的过程!
- 所有尝试过的调优手段及性能表现,需要留痕记录到结果文件中
- 不要自己判断性能表现,只要是正向的收益,就保留。负向的收益,代码回退,过程留痕
- 调优过程中遇到的报错及失败场景,请保留详细的过程及关键报错日志
4. 主动学习原则
⚠️ 重要:拒绝盲目调优,主动查询,主动学习
- 拒绝盲目无脑试错式调优
不瞎猜、不瞎改、不凭感觉乱配置。
- 以文档 / 资料库为依据
遇到问题查官方文档、权威资料、经典案例。
- 遇到不清晰的接口,不确定使用方法时,主动查询 API 接口文档
资料库
- 高性能编程实践 -- 介绍了很多高性能的编程案例,可以参考其中的高性能写法进行优化
- API 接口文档 -- 介绍了整个 pypto 仓库的所有接口及调优参数使用说明
5. 进度可视化原则
⚠️ 重要:调优开始时必须创建todo list,让用户清晰看到进度!
创建时机:精度校验通过后立即创建
Todo 模板:
## 📊 性能调优进度
### 目标
- 算子: [算子名称]
- 基准: [基准性能] us
- 目标: [目标性能] us (提升X倍)
### 进度
- ✅ 精度校验通过
- 🔄 [当前阶段]
- ⏸️ [待优化阶段]
### 性能记录
| 轮次 | 优化内容 | 执行时间 | 提升 |
|------|---------|---------|------|
| 基准 | - | XX us | - |
更新时机:
- 每次优化后(无论成功失败)
- 阶段切换时
- 性能提升>5%时
- 连续 3 次无提升时
状态看板(每完成 5 轮优化输出):
## 当前状态
- 性能: XX us (累计提升 XX%)
- 进度: ████████░░ XX%
- 成功率: X/Y 轮
步骤 0:确定性能调优目标
⚠️ 重要:必须明确性能目标,否则无法判断何时停止调优!
0.1 询问用户性能目标
必须询问用户:
请明确性能调优目标:
- 需要提升几倍性能?(例如:提升 5 倍)
- 或者需要达到多少执行时间?(例如:≤5000 us)
如果用户未说明,请主动询问,不要猜测!
0.2 计算具体目标值
根据用户输入计算具体目标:
原始执行时间 = 27469.66 us
目标执行时间 = 原始执行时间 / 5 = 5493.93 us
目标执行时间 = 5000 us
0.3 设置调优终止条件
自动终止条件:
- ✅ 达到性能目标(执行时间 ≤ 目标值)
- ✅ 核心利用率 > 80% 且 气泡率 < 10%
- ✅ 达到调优时间限制(默认 12 小时)
手动终止条件:
- 用户明确要求停止
步骤 1:算子用例执行及精度校验
1.1 设置环境变量
export TILE_FWK_DEVICE_ID=0
export PTO_TILE_LIB_CODE_PATH=${ASCEND_HOME_PATH:-/usr/local/Ascend/cann}/aarch64-linux
⚠️ 执行超时配置:
- 所有算子执行命令必须设置 timeout=300 秒(5 分钟)
- 使用 Bash 工具执行时,添加
timeout: 300000 参数(单位:毫秒)
验证环境:
npu-smi info
ls -la $PTO_TILE_LIB_CODE_PATH/include/pto/
1.2 编译策略
⚠️ 重要:首次进行精度校验,需要进行编译。
⚠️ 重要:如果只修改了算子测试或 impl 代码,直接运行即可,不需要编译。
| 修改类型 | 是否需要编译 | 原因 |
|---|
| 首次执行 | ✅ 需要编译 | 第一次执行需要更新 whl 包 |
| 算子测试或 impl 代码(*.py) | ❌ 不需要 | Python 代码即时生效 |
| framework 代码 | ✅ 需要编译 | C++ 代码需要重新编译 |
| python/pypto目录 | ✅ 需要编译 | 核心框架代码 |
编译命令(仅在需要时执行):
python3 build_ci.py -f python3 --disable_auto_execute
export PYTHONPATH=./pypto/build_out/:$PYTHONPATH
export LD_LIBRARY_PATH=./pypto/build_out/pypto/lib/:$LD_LIBRARY_PATH
1.3 执行算子用例
python3 custom/operator_name/operator.py --run-mode npu
1.4 精度校验(⛔ 强制检查点)
⛔ 禁止:必须完成本步骤并通过后,才能进入步骤2!
执行精度校验:
python3 custom/operator_name/operator.py --run-mode npu
⛔ 强制检查流程(每次调优修改后必须执行):
- ✅ 必须运行测试用例
- ✅ 必须看到 "passed/success" 或类似成功输出,出现 "time out" 都是失败
- ✅ 必须记录精度验证结果(包含验证时间和命令)
- ❌ 禁止:假设精度通过、跳过验证、使用之前的验证结果
⛔ 强制记录验证结果(必须填写):
### 精度验证记录
- 验证时间: YYYY-MM-DD HH:MM:SS
- 验证命令: python3 xxx.py --run-mode npu
- 验证结果: ✅ 通过 / ❌ 失败
- 关键输出: [粘贴 "test passed" 或报错信息]
✅ 通过:继续执行步骤 2(性能数据采集)
⚡ 立即创建调优Todo List:
## 📊 [算子名称] 性能调优进度
### 目标
- 基准性能: XX us
- 目标性能: XX us (提升X倍)
- 当前设备: NPU 卡 X
### 进度
- ✅ 精度校验通过
- 🔄 性能数据采集
- ⏸️ 开箱性能调优
- ⏸️ 深度性能调优
- ⏸️ 核内性能调优
- ⏸️ 生成调优报告
### 性能记录
| 轮次 | 优化内容 | 执行时间(us) | 变化 | 状态 |
|------|---------|-------------|------|------|
| 基准 | - | XX | - | ✅ |
然后启用性能数据采集(修改 debug_options)
❌ 失败:用户确认处理
失败处理流程:
-
首次失败:
- ⚠️ 不进行修复,需要用户自行确认
- 可以尝试换卡运行(更换 TILE_FWK_DEVICE_ID)
- 检查环境配置是否正确
-
换卡尝试:
npu-smi info
export TILE_FWK_DEVICE_ID=1
python3 custom/operator_name/operator.py --run-mode npu
-
多次失败或超时:
- 如果尝试多次(建议 3 次)仍然失败
- 或运行超时(建议 5 分钟)
- 停止调优,让用户确认是否继续
⚠️ 重要提示:
- 精度问题是算子实现的问题,不是性能调优能解决的
- 性能调优建立在精度正确的基础上
- 如果精度无法通过,应该先修复算子实现
步骤 2:性能数据采集
2.1 启用性能数据采集
在算子实现文件中,修改 @pypto.frontend.jit 装饰器:
@pypto.frontend.jit(
debug_options={"runtime_debug_mode": 1}
)
def kernel_function(...):
pass
⚠️ 重要提示:性能调优任务结束时,将修改的开关还原。
2.2 重新运行(不需要编译)
如果只修改了算子 impl 代码,直接运行即可:
python3 custom/operator_name/operator.py --run-mode npu
2.3 性能数据文件位置
执行后会在 output/output_*/ 目录下生成:
merged_swimlane.json - 泳道图数据文件
machine_runtime_operator_trace.json - 性能追踪文件
bubble_analysis.log - 气泡分析报告
步骤 3:性能数据分析
⚠️ 重要:这个过程中的优化建议用于后续分步骤性能分析及调优时使用,不要在这里立即开始优化!
3.1 分析性能
使用 perf-analyzer 子技能,分析性能数据,生成性能报告和优化建议。
Read perf-analyzer/SKILL.md
3.2 查看性能报告
性能报告保存在 output/output_时间戳/performance_analysis_report.md。
3.3 建立性能基准
必须记录基准性能:
## 基准性能(未优化)
- 执行时间: XXX us
- 核心利用率: XX%
- 气泡率: XX%
- 负载均衡度: XX%
步骤 4:分步骤性能分析及调优
⚠️ 重要:必须按顺序加载子技能获取详细调优指南!
4.0 调优流程总览
固定执行顺序:
第1步:开箱性能调优 (10%)
├─ 加载 tune-frontend 子技能
├─ 根据性能基准优化代码写法、TileShape、BLOCK_SIZE
├─ ⚠️ 不需要查看性能报告的详细分析,只需对比性能基准
└─ 快速建立性能基准
第2步:深度性能调优 (60%)
├─ 加载 tune-swimlane 子技能
├─ 查看性能报告,分析泳道图
├─ 优化调度策略:Stitch 调优、合图调优、L1Reuse 优化
└─ 基于性能报告指导优化方向
第3步:核内性能调优 (30%)
├─ 加载 tune-incore 子技能
├─ 查看性能报告,分析核内瓶颈
├─ 指令级优化、核内流水优化
└─ 特殊 Shape 处理
⚠️ 重要说明:
- 开箱性能调优:不需要查看性能报告的详细分析,但需要对比基准执行时间
- 深度性能调优:需要查看性能报告,分析泳道图和性能瓶颈
- 核内性能调优:需要查看性能报告,分析核内指令和流水线
每个阶段的进入和退出条件:
| 阶段 | 进入条件 | 退出条件 |
|---|
| 开箱调优 | 精度验证通过 | 性能达标 或 连续 5 次优化无提升 |
| 深度调优 | 开箱调优无法继续提升 | 性能达标 或 连续 8 次优化无提升 |
| 核内调优 | 深度调优无法继续提升 | 性能达标 或 达到理论性能上限 |
4.1 加载子技能
Read tune-frontend/SKILL.md
Read tune-swimlane/SKILL.md
Read tune-incore/SKILL.md
4.2 性能问题诊断
⚠️ 重要:开箱性能调优不需要查看性能报告!
开箱性能调优:直接根据性能基准(执行时间)进行优化,不需要分析详细性能报告
深度/核内性能调优:根据性能分析报告,使用决策树选择优化方向:
如果核心利用率低 (<50%):
├─ 检查任务粒度 → 增大TileShape
├─ 检查调度策略 → 使用L2亲和调度
└─ 检查数据访问 → 优化内存布局
如果气泡率高 (>20%):
├─ 检查Stitch配置 → 增大stitch_function_max_num
├─ 检查任务依赖 → 使用合图优化
└─ 检查循环展开 → 使用轴切块或loop_unroll
如果负载不均衡:
├─ 检查任务分配 → 调整TileShape
└─ 检查调度策略 → 调整device_sched_mode
4.3 迭代调优流程
┌───────────────────────────────────────┐
│ 迭代调优流程(每次循环) │
├───────────────────────────────────────┤
│ │
│ 1. 选择一个优化点 │
│ └─ 根据决策树或子技能指南 │
│ │
│ 2. 修改代码 │
│ └─ 每次只修改一个参数 │
│ │
│ 3. 验证精度 ⭐ │
│ ├─ 运行测试用例 │
│ ├─ 验证用例是否通过 │
│ └─ 失败,尝试解决,不行则回退修改 │
│ │
│ 4. 测试性能 │
│ ├─ 采集性能数据 │
│ ├─ 对比基准性能 │
│ └─ 计算提升百分比 │
│ │
│ 5. 记录结果 & 更新Todo ⭐ │
│ ├─ 性能提升:保留修改 │
│ ├─ 性能下降:回退修改 │
│ └─ 更新Todo List │
│ ├─ 成功: 标记✅并记录 │
│ └─ 失败: 标记❌并说明 │
│ │
│ 6. 检查终止条件 │
│ └─ 达到目标或无法提升则停止 │
│ │
│ 7. 状态看板(每 5 轮输出) │
│ └─ 展示当前进度和性能趋势 │
│ │
└───────────────────────────────────────┘
⚠️ 重要:每次修改都要验证精度,不要怕麻烦!
⚠️ 精度验证失败处理:
- 修改导致失败:尝试解决,不行则回退修改,记录失败原因,尝试其他优化方案
- 不要尝试修复精度问题,精度问题是算子实现问题,不是调优能解决的
关键原则:
- 每次只修改一个优化点
- 修改后立即测试性能和精度
- 精度失败,尝试解决,不行的话,则回退修改
- 性能回退则尝试其他优化点
- 每个阶段独立迭代,完成后再进入下一阶段
- 三个阶段顺序执行:开箱调优 → 深度调优 → 核内调优
- 当长时间达成调优目标,或者没有调优空间时,可以重新审视一下算子实现方式,重新设计开发算子
Todo 更新示例:
### 性能记录(持续更新)
| 轮次 | 优化内容 | 执行时间(us) | 变化 | 状态 |
|------|---------|-------------|------|------|
| 基准 | - | 79.34 | - | ✅ |
| 1 | BLOCK_SIZE_KV 128→64 | 68.54 | -13.6% | ✅ |
| 2 | unroll_list [8,4,2,1] | 74.44 | +8.6% | ❌回退 |
| 3 | cube_nbuffer {0:4} | 66.14 | -3.5% | ✅ |
### 当前进度
- 性能: 66.14 us (累计提升 16.6%)
- 进度条: ████████░░░░░░░░ 42%
- 成功率: 2/3 轮
状态看板示例(每 5 轮输出):
## 📊 调优状态看板
当前阶段: 深度性能调优
性能: 66.14 us | 累计提升: 16.6% | 目标: 39.67 us
进度: ████████░░░░░░░░ 42%
### 优化统计
- 总轮次: 10 轮
- 成功: 4 轮 (40%)
- 失败: 6 轮 (60%)
- 最佳优化: 增加并行度 (+13.6%)
### 当前瓶颈
1. ⭐⭐⭐ AIC核心利用率低 (13.63%)
2. ⭐⭐⭐ 气泡率高 (59.58%)
4.4 异常情况处理
连续 3 次优化无提升:
## ⚠️ 调优进展停滞
已连续 3 次优化无提升,可能原因:
1. 已达性能上限
2. 当前优化方向不佳
3. 需要算法层面改进
建议:
- 继续尝试其他优化
- 接受当前性能
- 重新设计算子
精度验证失败:
## ❌ 精度验证失败
- 失败轮次: 第X轮
- 当前优化: [优化内容]
- 处理: 尝试解决,但未生效,回退修改
Todo 更新: 标记当前优化为❌
步骤 5:生成性能调优报告
5.1 报告模板
⚠️ 重要:调优结束后,必须生成调优报告!
操作步骤:
- 输出最终状态看板:
## 📊 最终调优状态
### 目标达成
- 目标: 提升 1 倍 (XX → XX us)
- 实际: 提升XX% (XX → XX us)
- 达成率: XX%
- 状态: ✅达标 / ❌未达标
### 优化总结
- 总轮次: X轮
- 成功率: X%
- 耗时: XX分钟
- 最佳优化: [优化项] (+XX%)
### 性能趋势
基准 → 最终: XX us → XX us
-
根据实际调优过程填充模板内容
- 调优概述:算子名称、调优目标、实际达成、调优时长、调优轮次
- 性能对比:原始性能、最终性能、提升百分比
- 关键优化:列出所有有效的优化及提升比例
- 最佳配置:最终优化配置代码
- 调优记录:每轮调优的详细记录
-
要详细记录调优过程中跳过的出错问题,便于开发者后续解决
-
保存调优报告
报告示例:
# Flash Attention Score 性能调优报告
## 调优概述
- 算子名称: Flash Attention Score
- 调优目标: 提升 5 倍
- 实际达成: 提升 5.89 倍 (83.0%)
- 调优时长: 73 分钟
- 调优轮次: 11 轮
## 性能对比
| 指标 | 原始性能 | 最终性能 | 提升 |
|------|---------|----------|------|
| 执行时间 (us) | 27469.66 | 4665.66 | 83.0% |
| 核心利用率 | 46% | 85% | +39% |
| 气泡率 | 54% | 15% | -39% |
**性能倍数**: 5.89 倍
## 问题记录
常见错误
错误 1:跳过子技能直接调优
错误表现:
- 完成步骤3(性能数据分析)后,直接开始尝试优化
- 没有加载对应的子技能获取详细指南
- 凭经验或猜测进行调优
正确做法:
- 根据性能分析报告判断调优方向(参考步骤 4.2 决策流程)
- 读取对应子技能的 SKILL.md 文件
- 按照子技能中的详细指南执行调优
- 严格执行"修改一处 → 测试 → 验证"的迭代流程
错误 2:一次性修改多处优化点
错误表现:
正确做法:
- 每次只修改一个优化点
- 修改后立即测试
- 验证精度和性能
- 记录结果后再尝试下一个优化点
错误 3:不验证精度
错误表现:
- 修改代码后直接测试性能,不验证精度
- 认为小改动不会影响精度
正确做法:
- 每次修改都要验证精度,不要怕麻烦!
- 即使是小改动,也要验证精度
- 精度失败,不要立即回退,要进行简单分析尝试后,如果还是不能解决,则回退
参考资料
子技能
案例和文档