# External Cannbot Ops Pypto Op Perf Tune

> PyPTO 算子性能分析和自动调优技能。用于对生成及新开发的算子进行性能分析及自动调优，包括算子用例执行及精度校验、性能数据采集及分析、分步骤性能调优和生成性能分析报告。当用户需要分析 PyPTO 算子性能、进行性能调优、生成性能报告时使用此技能。触发词：算子性能调优、性能分析、自动调优、性能优化、泳道图分析。

- Skill: `ascend-ai-coding/external-cannbot-ops-pypto-op-perf-tune` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ascend-ai-coding/external-cannbot-ops-pypto-op-perf-tune`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ascend-ai-coding/external-cannbot-ops-pypto-op-perf-tune/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: UNKNOWN
- Author: ascend-ai-coding (https://skillmd.com/u/ascend-ai-coding)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ascend-ai-coding/external-cannbot-ops-pypto-op-perf-tune

---


# PyPTO 算子性能分析和自动调优

## 概述

此技能提供 PyPTO 算子性能调优的完整工作流程，包括精度校验、性能数据采集、性能分析和迭代调优。

## 核心原则

**⚠️⚠️⚠️ 非常重要：所有的调优验证必须上板执行，拒绝理论猜测，凭空捏造！！！**

### 1. 性能调优前提（最高优先级）
**⚠️ 非常重要：性能调优必须建立在精度正确的基础上！**

**⛔ 禁止：没有精度验证通过的记录，绝对禁止进入任何调优步骤！**

**核心要求**：
1. ✅ **精度必须通过**：首先确保算子精度校验通过，才能进行性能调优
2. ✅ **每次验证精度**：每次调优修改后，必须重新验证精度（不要怕麻烦！）
3. ❌ **精度失败不修复**：
   - 首轮失败：不进行修复，可以换卡尝试，多次失败让用户确认
   - 调优修改导致失败：可以进行简单分析后，如果不能解决，则回退修改，记录失败原因，尝试其他优化方案
   - ⚠️ 精度问题是算子实现问题，不是调优能解决的，可以尝试，但不强制解决

**详细处理流程**：见步骤 1.4（精度校验）和步骤 4.3（迭代调优流程）

### 2. 迭代优化原则

**⚠️ 重要：性能调优是一个循环迭代的过程！**

1. 修改一处改动点后，立即验证精度
2. 精度通过后，立即测试性能
3. **不要**全部改完再测
4. 对比修改前后的性能数据
5. 如果性能回退或者执行超时等异常情况，尝试修改，如果不能解决，则回退修改，记录失败，尝试其他方案
6. 重复上述过程直到达到目标性能

**⚠️ 注意：当长时间无法达到性能目标，或者识别没有调优空间时，可以尝试重新设计算子**

### 3. 留痕可溯原则

**⚠️ 重要：性能调优是一个可追溯的过程！**

1. 所有尝试过的调优手段及性能表现，需要留痕记录到结果文件中
2. 不要自己判断性能表现，只要是正向的收益，就保留。负向的收益，代码回退，过程留痕
3. 调优过程中遇到的报错及失败场景，请保留详细的过程及关键报错日志

### 4. 主动学习原则

**⚠️ 重要：拒绝盲目调优，主动查询，主动学习**

1. 拒绝盲目无脑试错式调优
不瞎猜、不瞎改、不凭感觉乱配置。
2. 以文档 / 资料库为依据
遇到问题查官方文档、权威资料、经典案例。
3. 遇到不清晰的接口，不确定使用方法时，主动查询 API 接口文档

**资料库**
1. [高性能编程实践](../../../models/) -- 介绍了很多高性能的编程案例，可以参考其中的高性能写法进行优化
2. [API 接口文档](../../../docs/api/) -- 介绍了整个 pypto 仓库的所有接口及调优参数使用说明

### 5. 进度可视化原则

**⚠️ 重要：调优开始时必须创建todo list，让用户清晰看到进度！**

**创建时机**：精度校验通过后立即创建

**Todo 模板**：
```markdown
## 📊 性能调优进度

### 目标
- 算子: [算子名称]
- 基准: [基准性能] us
- 目标: [目标性能] us (提升X倍)

### 进度
- ✅ 精度校验通过
- 🔄 [当前阶段]
- ⏸️ [待优化阶段]

### 性能记录
| 轮次 | 优化内容 | 执行时间 | 提升 |
|------|---------|---------|------|
| 基准 | - | XX us | - |
```

**更新时机**：
- 每次优化后（无论成功失败）
- 阶段切换时
- 性能提升>5%时
- 连续 3 次无提升时

**状态看板**（每完成 5 轮优化输出）：
```markdown
## 当前状态
- 性能: XX us (累计提升 XX%)
- 进度: ████████░░ XX%
- 成功率: X/Y 轮
```

---

## 步骤 0：确定性能调优目标

**⚠️ 重要：必须明确性能目标，否则无法判断何时停止调优！**

### 0.1 询问用户性能目标

**必须询问用户**：
```
请明确性能调优目标：
- 需要提升几倍性能？（例如：提升 5 倍）
- 或者需要达到多少执行时间？（例如：≤5000 us）
```

**如果用户未说明**，请主动询问，不要猜测！

### 0.2 计算具体目标值

根据用户输入计算具体目标：
```python
# 示例：用户要求提升 5 倍
原始执行时间 = 27469.66 us
目标执行时间 = 原始执行时间 / 5 = 5493.93 us

# 示例：用户要求执行时间≤5000 us
目标执行时间 = 5000 us
```

### 0.3 设置调优终止条件

**自动终止条件**：
1. ✅ 达到性能目标（执行时间 ≤ 目标值）
2. ✅ 核心利用率 > 80% 且 气泡率 < 10%
3. ✅ 达到调优时间限制（默认 12 小时）

**手动终止条件**：
1. 用户明确要求停止

---

## 步骤 1：算子用例执行及精度校验

### 1.1 设置环境变量

```bash
export TILE_FWK_DEVICE_ID=0  # 或其他可用 NPU 卡
export PTO_TILE_LIB_CODE_PATH=${ASCEND_HOME_PATH:-/usr/local/Ascend/cann}/aarch64-linux
```

**⚠️ 执行超时配置**：
- 所有算子执行命令必须设置 timeout=300 秒（5 分钟）
- 使用 Bash 工具执行时，添加 `timeout: 300000` 参数（单位：毫秒）

**验证环境**：
```bash
# 检查 NPU 设备
npu-smi info

# 检查路径存在
ls -la $PTO_TILE_LIB_CODE_PATH/include/pto/
```

### 1.2 编译策略

**⚠️ 重要：首次进行精度校验，需要进行编译。**
**⚠️ 重要：如果只修改了算子测试或 impl 代码，直接运行即可，不需要编译。**

| 修改类型 | 是否需要编译 | 原因 |
|---------|------------|------|
| 首次执行 | ✅ 需要编译 | 第一次执行需要更新 whl 包 |
| 算子测试或 impl 代码（*.py） | ❌ 不需要 | Python 代码即时生效 |
| framework 代码 | ✅ 需要编译 | C++ 代码需要重新编译 |
| python/pypto目录 | ✅ 需要编译 | 核心框架代码 |

**编译命令**（仅在需要时执行）：
```bash
# 执行编译
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 执行算子用例

```bash
python3 custom/operator_name/operator.py --run-mode npu
```

### 1.4 精度校验（⛔ 强制检查点)

**⛔ 禁止：必须完成本步骤并通过后，才能进入步骤2！**

**执行精度校验**：
```bash
python3 custom/operator_name/operator.py --run-mode npu
```
**⛔ 强制检查流程（每次调优修改后必须执行）**：
1. ✅ 必须运行测试用例
2. ✅ 必须看到 "passed/success" 或类似成功输出，出现 "time out" 都是失败
3. ✅ 必须记录精度验证结果（包含验证时间和命令）
4. ❌ 禁止：假设精度通过、跳过验证、使用之前的验证结果

**⛔ 强制记录验证结果（必须填写）**：
```markdown
### 精度验证记录
- 验证时间: YYYY-MM-DD HH:MM:SS
- 验证命令: python3 xxx.py --run-mode npu
- 验证结果: ✅ 通过 / ❌ 失败
- 关键输出: [粘贴 "test passed" 或报错信息]
```

**✅ 通过：继续执行步骤 2（性能数据采集）**

**⚡ 立即创建调优Todo List**：
```markdown
## 📊 [算子名称] 性能调优进度

### 目标
- 基准性能: XX us
- 目标性能: XX us (提升X倍)
- 当前设备: NPU 卡 X

### 进度
- ✅ 精度校验通过
- 🔄 性能数据采集
- ⏸️ 开箱性能调优
- ⏸️ 深度性能调优
- ⏸️ 核内性能调优
- ⏸️ 生成调优报告

### 性能记录
| 轮次 | 优化内容 | 执行时间(us) | 变化 | 状态 |
|------|---------|-------------|------|------|
| 基准 | - | XX | - | ✅ |
```

然后启用性能数据采集（修改 debug_options）

**❌ 失败：用户确认处理**


**失败处理流程**：

1. **首次失败**：
   - ⚠️ **不进行修复**，需要用户自行确认
   - 可以尝试换卡运行（更换 TILE_FWK_DEVICE_ID）
   - 检查环境配置是否正确

2. **换卡尝试**：
   ```bash
    # 查看可用 NPU 卡
   npu-smi info

   # 尝试其他卡
   export TILE_FWK_DEVICE_ID=1  # 或其他可用卡号
   python3 custom/operator_name/operator.py --run-mode npu
   ```

3. **多次失败或超时**：
   - 如果尝试多次（建议 3 次）仍然失败
   - 或运行超时（建议 5 分钟）
   - **停止调优**，让用户确认是否继续

**⚠️ 重要提示**：
- 精度问题是算子实现的问题，不是性能调优能解决的
- 性能调优建立在精度正确的基础上
- 如果精度无法通过，应该先修复算子实现

---

## 步骤 2：性能数据采集

### 2.1 启用性能数据采集

在算子实现文件中，修改 `@pypto.frontend.jit` 装饰器：

```python
@pypto.frontend.jit(
    debug_options={"runtime_debug_mode": 1}  # 启用性能数据采集
)
def kernel_function(...):
    # 算子实现
    pass
```

**⚠️ 重要提示**：性能调优任务结束时，将修改的开关还原。

### 2.2 重新运行（不需要编译）

如果只修改了算子 impl 代码，直接运行即可：
```bash
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` 子技能，分析性能数据，生成性能报告和优化建议。
```bash
# 加载性能分析技能
Read perf-analyzer/SKILL.md
```

### 3.2 查看性能报告

性能报告保存在 `output/output_时间戳/performance_analysis_report.md`。

### 3.3 建立性能基准

**必须记录基准性能**：
```markdown
## 基准性能（未优化）
- 执行时间: 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 加载子技能

```bash
# 第1步：加载开箱性能调优指南
Read tune-frontend/SKILL.md

# 第2步：加载深度性能调优指南
Read tune-swimlane/SKILL.md

# 第3步：加载核内性能调优指南
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 轮输出）            │
│     └─ 展示当前进度和性能趋势          │
│                                       │
└───────────────────────────────────────┘
```

**⚠️ 重要：每次修改都要验证精度，不要怕麻烦！**

**⚠️ 精度验证失败处理**：
- **修改导致失败**：尝试解决，不行则回退修改，记录失败原因，尝试其他优化方案
- **不要尝试修复精度问题**，精度问题是算子实现问题，不是调优能解决的

**关键原则**：
1. 每次只修改一个优化点
2. 修改后立即测试性能和精度
3. 精度失败，尝试解决，不行的话，则回退修改
4. 性能回退则尝试其他优化点
5. **每个阶段独立迭代**，完成后再进入下一阶段
6. 三个阶段顺序执行：开箱调优 → 深度调优 → 核内调优
7. 当长时间达成调优目标，或者没有调优空间时，可以重新审视一下算子实现方式，重新设计开发算子

**Todo 更新示例**：
```markdown
### 性能记录（持续更新）
| 轮次 | 优化内容 | 执行时间(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 轮输出）：
```markdown
## 📊 调优状态看板

当前阶段: 深度性能调优
性能: 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 次优化无提升**：
```markdown
## ⚠️ 调优进展停滞

已连续 3 次优化无提升，可能原因：
1. 已达性能上限
2. 当前优化方向不佳
3. 需要算法层面改进

建议：
- 继续尝试其他优化
- 接受当前性能
- 重新设计算子
```

**精度验证失败**：
```markdown
## ❌ 精度验证失败

- 失败轮次: 第X轮
- 当前优化: [优化内容]
- 处理: 尝试解决，但未生效，回退修改

Todo 更新: 标记当前优化为❌
```

---

## 步骤 5：生成性能调优报告

### 5.1 报告模板

**⚠️ 重要：调优结束后，必须生成调优报告！**

**操作步骤**：

1. **输出最终状态看板**：
```markdown
## 📊 最终调优状态

### 目标达成
- 目标: 提升 1 倍 (XX → XX us)
- 实际: 提升XX% (XX → XX us)
- 达成率: XX%
- 状态: ✅达标 / ❌未达标

### 优化总结
- 总轮次: X轮
- 成功率: X%
- 耗时: XX分钟
- 最佳优化: [优化项] (+XX%)

### 性能趋势
基准 → 最终: XX us → XX us
```

2. 根据实际调优过程填充模板内容
   - 调优概述：算子名称、调优目标、实际达成、调优时长、调优轮次
   - 性能对比：原始性能、最终性能、提升百分比
   - 关键优化：列出所有有效的优化及提升比例
   - 最佳配置：最终优化配置代码
   - 调优记录：每轮调优的详细记录

3. 要详细记录调优过程中跳过的出错问题，便于开发者后续解决

4. 保存调优报告

**报告示例**：
```markdown
# 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（性能数据分析）后，直接开始尝试优化
- 没有加载对应的子技能获取详细指南
- 凭经验或猜测进行调优

**正确做法**：
1. 根据性能分析报告判断调优方向（参考步骤 4.2 决策流程）
2. 读取对应子技能的 SKILL.md 文件
3. 按照子技能中的详细指南执行调优
4. 严格执行"修改一处 → 测试 → 验证"的迭代流程

### 错误 2：一次性修改多处优化点

**错误表现**：
- 同时修改多个配置参数
- 全部修改完才测试性能

**正确做法**：
- 每次只修改一个优化点
- 修改后立即测试
- 验证精度和性能
- 记录结果后再尝试下一个优化点

### 错误 3：不验证精度

**错误表现**：
- 修改代码后直接测试性能，不验证精度
- 认为小改动不会影响精度

**正确做法**：
- **每次修改都要验证精度，不要怕麻烦！**
- 即使是小改动，也要验证精度
- 精度失败，不要立即回退，要进行简单分析尝试后，如果还是不能解决，则回退

---

## 参考资料

### 子技能
- [perf-analyzer](perf-analyzer/SKILL.md) - 性能分析
- [tune-frontend](tune-frontend/SKILL.md) - 开箱性能调优
- [tune-swimlane](tune-swimlane/SKILL.md) - 深度性能调优
- [tune-incore](tune-incore/SKILL.md) - 核内性能调优

### 案例和文档
- [性能调优文档](../../../docs/tutorials/debug/performance.md)
- [Matmul 高性能编程](../../../docs/tutorials/debug/matmul_performance_guide.md)
- [性能优化案例](../../../docs/tutorials/debug/performance_case_quantindexerprolog.md)
- [性能调优报告模板](./perf-analyzer/templates/performance_report_template.md)
- [高性能编程实践](../../../models/)
- [API 接口文档](../../../docs/api/)

