PyPTO 算子性能分析报告模板深度解读:从数据采集到瓶颈定位的完整实战指南
【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym
导读
本文围绕 CANN pypto-gym 仓库中 PyPTO 算子性能分析报告模板 展开,系统讲解 PyPTO 算子性能分析报告从数据采集、指标计算、性能评级到瓶颈定位与调优方向建议的完整方法论。读完本文,你将掌握如何借助 perf-analyzer 技能与analyze_perf.py脚本自动生成性能分析报告,理解 AIC/AIV 核心利用率、气泡率、负载均衡度等核心指标的计算口径,并能够依据报告中的评级标准与调优方向建议,驱动开箱调优、深度调优与核内调优三个阶段的迭代流程。
1. 模板定位:性能分析报告在 PyPTO 调优流程中的位置
PyPTO(PyTorch 风格算子编程框架)算子在昇腾 NPU 上运行时,其性能特征由核上计算(AICore)、数据搬运(MTE)、任务调度等多层因素共同决定。为了把"性能不好"这种模糊感受转化为可量化、可对比、可驱动决策的工程数据,pypto-op-perf-tune技能家族定义了完整的调优流水线,而性能分析报告正是其中连接"数据采集"与"分阶段调优"的关键枢纽:
- S2_COLLECT(性能数据采集):在算子 JIT 装饰器中添加
debug_options={"runtime_debug_mode": 1}后重新运行算子,产出泳道图、气泡分析、性能追踪三类数据文件; - S3_ANALYZE(性能数据分析):加载 perf-analyzer 技能,从性能数据中提取关键指标、计算性能评级、识别性能瓶颈,并生成
performance_analysis_report.md; - S4_TUNE(分步骤调优):基于报告中的瓶颈分析与优化建议,依次进入开箱调优(tune-frontend)、深度调优(tune-swimlane)、核内调优(tune-incore)三个阶段;
- S5_REPORT(生成调优报告):最终以阶段交接摘要为骨架,整合 perf-analyzer 报告的性能数据与最终状态看板,形成完整调优报告。
因此,这份性能分析报告模板不仅是 perf-analyzer 子技能的产物,也是整个 pypto-op-perf-tune 主技能 状态机中 S3_ANALYZE 阶段的交付物标准。它定义了报告应包含的 9 个核心章节,确保每一份报告都覆盖"指标—统计—评级—瓶颈—建议—数据位置"这一完整闭环。
2. 报告的两种生成方式
2.1 脚本自动生成(推荐)
analyze_perf.py 是仓库提供的一键生成脚本,它从bubble_analysis.log中解析核心指标、计算统计量、评级与瓶颈,并自动在 output 目录下写出performance_analysis_report.md。其核心调用链为:
main() → _require_output_dir / _require_bubble_log(定位数据) → parse_bubble_analysis(正则解析每个核心的任务数/工作时间/等待时间) → calculate_performance_metrics(计算利用率、气泡率、负载均衡度等) → analyze_bottlenecks(识别利用率/气泡/负载/前驱等待四类瓶颈) → generate_optimization_suggestions(按优先级生成优化建议) → generate_report(按模板拼装 9 节报告并落盘)使用方法:
# 传入 output 目录路径(包含 bubble_analysis.log 的具体时间戳目录) python3 cannbot-skills/ops/pypto-op-perf-tune/perf-analyzer/scripts/analyze_perf.py <output_dir> # 示例:在算子目录下执行时的 output 位置 python3 scripts/analyze_perf.py custom/operator_name/output/output_20260304_171658_543682_529508脚本对输入做了充分的容错设计(见 analyze_perf.py):
- output_dir 定位:优先查找
output_dir/bubble_analysis.log;找不到时自动递归搜索子目录中的output_*/bubble_analysis.log; - 错误提示:目录不存在或日志缺失时,会给出"output 目录相对执行算子命令时的工作目录"的提示,并建议用
find . -name bubble_analysis.log快速定位。
2.2 手动填充
当需要人工撰写或补充报告细节时,直接以 performance_report_template.md 为骨架,将花括号占位符(如{max_work_time}、{avg_core_utilization})替换为实测数值即可。模板明确要求报告必须覆盖 6 项核心内容:核心性能指标、性能指标统计、性能评级、性能瓶颈分析、性能优化建议、性能数据文件位置(另含调优方向、调优记录与总结章节)。
3. 核心性能指标:读懂 AIC / AIV 核心表
报告第 1 节"核心性能指标"是全篇的数据地基。它由两部分组成:
3.1 算子实际执行时间
**{max_work_time} us**这一数值是所有核心中Core Total Work Time的最大值,对应运行 stdoutAICORE Prof Summary中的AICore End-to-End Time。注意,这是性能调优的核心判据,而非 wall time——wall time 包含 host 下发开销(AICPU task 调度、gather 等),不能反映核上真实计算效率。主技能中明确声明:调优全程「执行时间」与「AICore E2E Time」为同一指标,禁止用 wall time 作为调优判据。
3.2 AIC 与 AIV 核心性能指标表
模板为 AIC(AI Cube 核心,承担 Matmul 等矩阵运算)和 AIV(AI Vector 核心,承担逐元素/归约类计算)分别提供一张指标表:
| 核心 | 任务数 | 总工作时间(us) | 总等待时间(us) | 等待调度时间(us) | 等待前驱时间(us) | AicoreTime(us) | 核心利用率(%) | 气泡率(%) |
|---|---|---|---|---|---|---|---|---|
| AIC_0 | {task_num} | {total_work_time} | {total_wait_time} | {wait_schedule_time} | {wait_predecessor_time} | {aicore_time} | {core_utilization} | {bubble_rate} |
各列的数据来源与含义可对照 analyze_perf.py 中的 CoreMetrics 数据类 理解:
- 任务数(task_num):该核心上被调度执行的任务个数;
- 总工作时间(total_work_time):核心从开始到结束的完整 span,包含实际计算与等待;
- 总等待时间(total_wait_time):等待调度与等待前驱的合计;
- 等待调度时间(wait_schedule_time):任务排队等待被调度的时间,即"气泡"的直接来源;
- 等待前驱时间(wait_predecessor_time):因上游任务未完成而产生的依赖等待;
- AicoreTime(核心实际工作时间):
AicoreTime = 总工作时间 - 总等待时间,这是衡量单核心真实计算量的指标; - 核心利用率:
AicoreTime / (AicoreTime + 等待总时间) × 100%; - 气泡率:
等待调度时间 / (AicoreTime + 等待调度时间) × 100%。
从源码看,parse_bubble_analysis通过正则\[(AIC_\d+|AIV_\d+)\] Execute task num:(\d+)\s+Core Total Work Time:...逐行解析bubble_analysis.log,将每个核心的六项原始数据还原为CoreMetrics对象,再由属性计算派生指标。脚本还对所有可能的除零场景做了保护(时间为 0 时返回 0),保证任意数据下脚本都能正常产出报告。
4. 性能指标统计:平均值与负载均衡
报告第 2 节汇总全局统计量,为后续评级提供输入:
| 指标 | 数值 |
|---|---|
| 平均核心利用率 | {avg_core_utilization}% |
| 平均气泡率 | {avg_bubble_rate}% |
| AIC 平均核心利用率 | {avg_aic_utilization}% |
| AIV 平均核心利用率 | {avg_aiv_utilization}% |
| AIC 平均气泡率 | {avg_aic_bubble_rate}% |
| AIV 平均气泡率 | {avg_aiv_bubble_rate}% |
| 核心负载均衡度 | {load_balance}% |
- 平均核心利用率 / 平均气泡率:所有核心对应指标的算术平均(
_average函数实现,空列表返回 0); - AIC / AIV 分项统计:按核心名前缀(
AIC/AIV)分组后分别求平均,便于区分 Cube 侧与 Vector 侧的差异; - 核心负载均衡度:由 AIC 核心实际工作时间的标准差计算,公式为
(1 - 标准差 / 均值) × 100%,越接近 100% 说明各 AIC 核心工作时间越均衡。当 AIC 核心数 ≤ 1 时直接返回 100。
负载均衡度之所以重要,是因为算子的执行时间取决于"最慢的核心"——只要有一个核心拖尾,整体 AICore E2E Time 就会被拉长。因此负载不均衡通常与核心利用率低相伴出现,是深度调优(tune-swimlane)阶段的首要排查对象。
5. 性能评级:星级标准与综合评级
报告第 3 节将量化指标转化为直观的星级评价,便于快速判断算子处于"优秀/良好/一般/较差/很差"的哪个档位。
5.1 单项评级表
| 指标 | 当前值 | 目标值(⭐⭐⭐⭐⭐) | 评级 | 描述 |
|---|---|---|---|---|
| 核心利用率 | {avg_core_utilization}% | >90% | {util_rating} | {util_desc} |
| 气泡率 | {avg_bubble_rate}% | <2% | {bubble_rating} | {bubble_desc} |
| 负载均衡度 | {load_balance}% | >90% | {balance_rating} | {balance_desc} |
5.2 评级标准表
模板给出了三项指标共用的星级阈值(核心利用率、气泡率、负载均衡度均为同表口径):
| 评分 | 核心利用率 | 气泡率 | 负载均衡度 |
|---|---|---|---|
| ⭐⭐⭐⭐⭐ | >90% | <2% | >90% |
| ⭐⭐⭐⭐ | >80% | <5% | >80% |
| ⭐⭐⭐ | >60% | <10% | >60% |
| ⭐⭐ | >50% | <20% | >50% |
| ⭐ | <50% | >20% | <50% |
在脚本实现中,评级逻辑封装在get_rating/_higher_is_better_rating/_lower_is_better_rating:核心利用率与负载均衡度是"越高越好"(阈值 90/80/60/50),气泡率是"越低越好"(阈值 2/5/10/20),描述分别为优秀/良好/一般/较差/很差。
5.3 综合评级
**{overall_rating} ({overall_desc})**综合评级由三项单项描述映射为分数后取平均得到:优秀=5、良好=4、一般=3、较差=2、很差=1,平均分 ≥4.5 为 ⭐⭐⭐⭐⭐,≥3.5 为 ⭐⭐⭐⭐,≥2.5 为 ⭐⭐⭐,≥1.5 为 ⭐⭐,否则为 ⭐(见_overall_rating)。综合评级是报告结尾"当前状态"部分的直接引用项,也决定了调优是否继续推进。
6. 性能瓶颈分析:从症状到根因
报告第 4 节基于第 2 节的统计量自动推导瓶颈。脚本的analyze_bottlenecks依次检查四类候选:
| 瓶颈类型 | 触发阈值 | 严重程度 | 典型建议 |
|---|---|---|---|
| 核心利用率低 | 平均利用率 < 50% | 高 | 调整 Tilesize 增大算术强度,或使用 L2 亲和调度 |
| 核心利用率偏低 | 平均利用率 < 70% | 中 | 检查任务调度策略,优化内存访问 |
| 气泡率过高 | 平均气泡率 > 20% | 高 | 增大任务粒度,使用 loop_unroll 优化 |
| 气泡率偏高 | 平均气泡率 > 10% | 中 | 优化调度策略,使用 L1Reuse 优化 |
| 核心负载不均衡 | 负载均衡度 < 60% | 高 | 调整任务分配策略,优化 tile size |
| 核心负载略有不均 | 负载均衡度 < 80% | 中 | 检查任务分配是否均匀 |
| 等待前驱时间过长 | AIC 最大等待前驱 > 500us | 中 | 减少任务依赖,使用 sg_set_scope 合并子图 |
6.1 瓶颈条目结构
模板中每个瓶颈按统一结构描述,便于报告阅读者快速评估优先级:
#### 瓶颈 1: {瓶颈名称} - **严重程度**: {高/中/低} - **描述**: {详细描述} - **影响**: {对性能的影响程度}6.2 瓶颈分析图示
模板用 ASCII 条形图直观展示三项核心指标与目标值的差距,例如:
性能瓶颈分析: ┌──────────────────────────────────────────┐ │ 核心利用率: {avg_core_utilization}% │ │ ████████████████████░░░░░░░░░░░░░░░░░░░░ │ │ 目标: >90% │ ├──────────────────────────────────────────┤ │ 气泡率: {avg_bubble_rate}% │ │ ░░░░░░░░░░░░░░░░░░░░████████████████████ │ │ 目标: <2% │ ├──────────────────────────────────────────┤ │ 负载均衡度: {load_balance}% │ │ ████████████████████████████░░░░░░░░░░░░ │ │ 目标: >90% │ └──────────────────────────────────────────┘实心块占比直观反映当前值与目标的差距:利用率与负载均衡度实心块越长越好,气泡率则相反。当脚本检测不到任何瓶颈时,第 4 节输出"未发现明显的性能瓶颈,性能表现良好"。
6.3 瓶颈与优化点编号的对应关系
模板第 4 节负责"定位问题",而具体解法由 optimization_catalog.md 的"按症状索引"章节承接——这是调优流程中连接"分析"与"行动"的关键索引表,例如:
- 气泡率 > 10%(症状 A):可尝试 F-2 循环体计算量、F-8 内层 unroll、S-9 Stitch 调优(
stitch_function_max_num: 128)、S-14 A5 Mix 合图、S-20 max_workspace_kb 等; - 核心利用率 < 50%(症状 B):可尝试 F-1 任务粒度检查、F-9 Cube TileShape、S-2 核填充、S-20 max_workspace_kb 等;
- 负载不均衡(症状 C,AicoreTime 差异 > 20%):可尝试 S-3 负载均衡分析、S-11/S-12 TileShape 深度调优、S-4 手动合图;
- 单 task 耗时过长(症状 D):可尝试 I-1 小 Shape 矩阵乘、I-10 合并 gather、I-11 view 复用等核内优化。
7. 性能优化建议:按优先级分层执行
报告第 5 节将瓶颈分析结果转化为可执行清单,并按"高→中→低"三级优先级组织(模板还特别强调优化纪律:优先使用高优先级建议、每次只修改一个优化点、修改后立即测试性能、精度失败或性能回退时回退修改)。
脚本的generate_optimization_suggestions依据瓶颈严重程度自动归类,并附带可直接复制的代码示例,例如:
- 核心利用率 < 50% 时的高优先级建议:
- 使用 L2 亲和调度:
@pypto.frontend.jit(runtime_options={"device_sched_mode": 1}) - 调整 Cube Tilesize:
pypto.set_cube_tile_shapes([128, 128], [128, 512], [128, 128])
- 使用 L2 亲和调度:
- 气泡率 > 10% 时的高/中优先级建议:
- 使用 loop_unroll:
pypto.loop_unroll(A.shape[0] // 64, unroll_list=[64, 16, 4], ...) - 使用 L1Reuse:
pypto.set_pass_options(cube_l1_reuse_setting={0: 8})
- 使用 loop_unroll:
- 负载均衡度 < 80% 时的中优先级建议:调整 vec tile 使任务分配更均匀。
这些建议与 optimization_catalog.md 中的 F/S/I 系列优化点编号一一对应,且均可在后续阶段的子技能 SKILL 文档中找到完整的操作指南与约束条件。例如 Stitch 调优对应 S-9,配置示例为runtime_options={"stitch_function_max_num": 128},参数过小(如 1)时每个任务需同步、调度开销大,过大(如 512)时调度耗时与 workspace 增加;而 TileShape 配置则需参考 npu-memory-arch.md 中的硬件约束——例如 950PR(DAV_3510)上 L0C 为 256KB、单 AIV 可用 UB 为 248KB,这是设置 tile 并发占用与判断 spill 的硬边界。
8. 调优方向建议:三大阶段的衔接入口
报告第 6 节是连接"分析"与"调优"的桥梁,它根据当前指标动态给出后续行动建议,并明确指向对应的子技能:
8.1 开箱性能调优(tune-frontend)
- 是否需要:核心利用率 < 50% 或气泡率 > 20% 时为"是";
- 调优重点:Loop 写法优化、TileShape 设置优化、数据操作优化;
- 详细指南:加载 tune-frontend 技能。
开箱调优关注代码级差异,例如:静态轴应使用 Python for 而非pypto.loop(但 n_kv/group 等参与 offset 计算的语义维度循环须保留);外层动态轴范围大时应切块、内层动态轴范围大时应 loop_unroll;以及 Reshape 全局优化(原始输入 reshape 外提 +inplace=True)等 F 系列优化点。
8.2 深度性能调优(tune-swimlane)
- 是否需要:气泡率 > 10% 或负载均衡度 < 80% 时为"是";
- 调优重点:Stitch 调优、TileShape 深度调优、合图调优、调度策略调优;
- 详细指南:加载 tune-swimlane 技能。
深度调优以泳道图分析为核心,典型手段包括:stitch_function_max_num调整、device_sched_mode(值域 [0,3])调度策略、sg_set_scope手动合图、以及 A5 平台(npuarch == 'DAV_3510')专属的 Mix 合图(S-14)与 VF 融合(S-16~S-18)。注意 Mix 合图存在严格的硬性限制(CV 间数据传递须 1:N 或 N:1、shape 变化单调、UB 并发 < 248KB 等),配置前必须先完成数据流分析。
8.3 核内性能调优(tune-incore)
- 是否需要:核心利用率 ≥ 70% 且气泡率 < 10% 时为"可能需要";否则待前两阶段完成后评估;
- 调优重点:特殊 Shape 处理、冗余计算优化、尾轴优化、Operation 实现检查;
- 详细指南:加载 tune-incore 技能。
核内调优面向单 task 指令级优化,如小 Shape 矩阵乘的 Vector 预处理(典型案例从 500us 优化到 40us)、L2 Cache 策略(tensor.set_cache_policy(pypto.CachePolicy.NONE_CACHEABLE, True))、submit_before_loop=True计算搬运重叠、valid_shape尾块零填充避免,以及 DDR 往返优化(I-10 合并 gather、I-11 view 复用)。
9. 性能数据文件位置与可视化
报告第 7 节记录了本次分析的原始数据出处,保证报告可追溯、可复现:
| 文件类型 | 路径 |
|---|---|
| 泳道图 | {output_dir}/merged_swimlane.json |
| 气泡分析 | {output_dir}/bubble_analysis.log |
| 性能追踪 | {output_dir}/machine_runtime_operator_trace.json |
| 本报告 | {output_dir}/performance_analysis_report.md |
这些文件位于执行算子命令时工作目录下的output/output_<时间戳>/中(在算子目录下执行则为<算子目录>/output/output_*/,在项目根目录执行则为./output/output_*/)。其中:
- merged_swimlane.json:泳道图数据,展示各核心任务的执行顺序、耗时、气泡与依赖关系,可通过 PyPTO Toolkit 插件或官方 Perfetto 在线工具上传可视化分析;
- bubble_analysis.log:气泡分析报告,是
analyze_perf.py的数据源; - machine_runtime_operator_trace.json:运行时算子级性能追踪。
泳道图是深度调优阶段的核心工具——tune-swimlane 技能 强调每次进入该阶段必须重新采集最新数据,禁止复用旧轮次的泳道图(代码修改后性能特征已变,旧数据会导致错误结论)。
10. 调优记录与总结:让迭代有据可依
10.1 调优记录表
报告第 8 节以轮次为单位记录每次优化的前后对比,是迭代式调优的过程证据:
| 轮次 | 优化内容 | 修改前执行时间(us) | 修改后执行时间(us) | 提升比例 | 精度结果 |
|---|---|---|---|---|---|
| 1 | {优化内容} | {time} | {time} | {percent}% | {通过/失败} |
该表与主技能的迭代纪律强绑定:每次修改一个参数 → 立即验证精度(输出必须含 "passed"/"success")→ 采集性能对比 → 记录结果 → 判断是否继续。精度失败或性能回退的尝试必须记录(避免重试),这正是 optimization_catalog.md 中"已失败优化(避免重试)"表的设计初衷。
10.2 总结章节
报告第 9 节收束全文,给出三要素:
- 当前状态:性能评级(引用第 3 节综合评级)、主要瓶颈列表、推荐的调优方向;
- 下一步行动:按调优方向建议的顺序执行、每次优化后验证精度并记录、达到性能目标后生成最终报告;
- 报告元信息:报告生成时间与 PyPTO 版本(模板末尾),保证不同轮次报告之间的可比性。
11. 报告在真实调优流程中的使用建议
结合 pypto-op-perf-tune 主技能 的状态机,性能分析报告在每个调优轮次中承担三种角色:
- 基线锚点:调优开始前必须记录基准性能(AICore End-to-End Time、核心利用率、气泡率、负载均衡度),此后每次优化都与基线对比,判断优化方向是否正确——特别强调"以 AICore E2E Time 下降为准",若 AICore E2E Time 上升而 wall time 下降,说明开销被从 host 转移到了核上,应回退;
- 症状索引:报告中的瓶颈类型直接映射到 optimization_catalog 的症状 A/B/C/D,可快速锁定 F/S/I 系列优化点编号,再加载对应子技能获取操作指南;
- 迭代记录:每轮优化结果写入第 8 节调优记录表,最终整合进
{op_name}_tuning_report.md,形成从"性能数据 → 性能分析 → 调优决策 → 效果验证"的完整证据链。
结语
PyPTO 算子性能分析报告模板将昇腾 NPU 上晦涩的硬件行为(核间气泡、调度等待、负载倾斜)转化为结构化的九节报告:核心指标给出事实、统计与评级给出判断、瓶颈与建议给出方向、数据位置与调优记录给出可追溯性。配合 perf-analyzer 技能与analyze_perf.py脚本,它可以被无缝嵌入到 pypto-op-perf-tune 的自动化调优流程中,成为驱动开箱调优、深度调优与核内调优迭代闭环的可靠数据基础。无论你是手工分析还是脚本自动生成,遵循本模板的结构与指标口径,就能产出一份决策友好、可复现、可对比的高质量性能分析报告。
【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考