PyPTO 性能调优环境变量 PYPTO_PROF_PMU_EVENT_TYPE 详解:AI Core PMU 事件组选择与采集流程
【免费下载链接】pyptoPyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto
PYPTO_PROF_PMU_EVENT_TYPE 是 CANN PyPTO 用于选择 PMU(Performance Monitoring Unit,性能监控单元)数据采集模式的环境变量,通过指定不同的事件组编号,开发者可以采集 AI Core 上不同类型的硬件性能事件,用于算子性能瓶颈分析。本文基于该环境变量的官方说明文档,结合 pmu_common.cpp、tilefwk_pmu_to_csv.py 等仓库源码,完整介绍其取值含义、两种芯片架构下的事件组差异、从环境变量设置到 msprof 采集再到 CSV 解析的完整实操流程,帮助开发者在算子调优中快速定位计算利用率、流水线占用、访存带宽等瓶颈。
功能概述:PMU 数据采集模式的选择入口
PMU 是现代处理器中关键的硬件模块,专门用于监控和分析处理器的运行性能。在 AI Core 上,PMU 内部有多个可编程计数器,每个计数器可监控一种或多种事件,例如指令执行周期、缓存命中/缺失、存储体读写请求等。由于可编程计数器数量有限,PyPTO 将常用事件预定义为多组"事件组",每个事件组对应一种采集主题。
PYPTO_PROF_PMU_EVENT_TYPE 环境变量即用于选择具体的事件组:
- 类型:整数
- 取值范围:
1、2、4、5、6、7、8 - 默认值:
2
从源码 pmu_common.cpp 可以看到,各取值的语义定义如下:
| 取值 | 源码常量 | 采集主题 |
|---|---|---|
1 | ARITHMETIC_UTILIZATION | 算数(算术单元)利用率,如 Cube/Vector 各类指令执行计数 |
2 | PIPE_UTILIZATION | 流水线(Pipe)利用率,如 Vector/Cube/Scalar/MTE 各流水线忙碌周期、ICache 命中率 |
4 | MEMORY | 内存访问,如 UB/L1/L2/主存(Main Memory)的读请求、写请求 |
5 | MEMORY_L0 | L0 级缓存(L0A/L0B/L0C)的读/写请求 |
6 | RESOURCE_CONFLICT_RATION | 资源冲突率,如 Bank 冲突、Vector 资源竞争导致的停顿周期 |
7 | MEMORY_UB | UB(Unified Buffer)读写带宽类事件 |
8 | L2_CACHE | L2 缓存命中/未命中及 victim 替换等事件 |
两种芯片架构下的事件组映射
同一事件组编号在不同芯片架构上对应不同的硬件事件 ID 集合。从 pmu_common.cpp 的SetPmuEventTypeDAV2201与SetPmuEventTypeDAV3510两个函数可以看出,DAV2201 与 DAV3510 使用完全不同的寄存器事件编码(十六进制事件 ID),且事件数量上限也不同(PMU_EVENT_TYPE_MAX_DAV2201 = 8、PMU_EVENT_TYPE_MAX_DAV3510 = 10)。例如:
- 算数利用率组(取值为
1):DAV2201 对应 7 个事件(0x49~0x4f),DAV3510 对应 2 个事件(0x323、0x324); - 流水线利用率组(取值为
2,默认):DAV2201 为 8 个事件(0x08、0x0a、0x09、0x0b、0x0c、0x0d、0x55、0x54),DAV3510 为 9 个事件(0x501、0x301、0x1、0x701、0x202、0x203、0x34、0x35、0x714); - L2 缓存组(取值为
8):DAV2201 为 6 个事件(0x500~0x50a),DAV3510 为 6 个事件(0x424、0x425、0x426、0x42a、0x42b、0x42c)。
因此,环境变量的取值决定了"采集哪个主题",而具体"采集哪些寄存器事件"由运行时根据当前芯片架构自动映射,开发者无需关心底层事件 ID。
事件组的语义列名(解析结果对应列)
PMU 数据解析脚本 tilefwk_pmu_to_csv.py 中维护了两套事件组列名表table_pmu_header_2201与table_pmu_header_3510,可供开发者对照理解每个事件组输出的数据含义:
| 取值 | dav_2201 列名 | dav_3510 列名 |
|---|---|---|
1算数利用率 | cube_fp16_exec、cube_int8_exec、vec_fp32_exec、vec_fp16_128lane_exec、vec_fp16_64lane_exec、vec_int32_exec、vec_misc_exec | cube_fp_instr_busy、cube_int_instr_busy |
2流水线利用率 | vec_busy_cycles、cube_busy_cycles、scalar_busy_cycles、mte1_busy_cycles、mte2_busy_cycles、mte3_busy_cycles、icache_miss、icache_req | pmu_idc_aic_vec_busy_o、cube_instr_busy、scalar_instr_busy、mte1_instr_busy、mte2_instr_busy、mte3_instr_busy、icache_req、icache_miss、pmu_fix_instr_busy |
4内存访问 | ub_read_req、ub_write_req、l1_read_req、l1_write_req、l2_read_req、l2_write_req、main_read_req、main_write_req | bif_sc_pmu_read_main_instr_core、bif_sc_pmu_write_main_instr_core、pmu_aiv_ext_rd_ub_instr、ub_pmu_vec_rd_ub_acc、pmu_aiv_ext_wr_ub_instr、ub_pmu_vec_wr_ub_acc、pmu_rd_l1_instr、pmu_wr_l1_instr |
5L0 内存访问 | l0a_read_req、l0a_write_req、l0b_read_req、l0b_write_req、l0c_read_req、l0c_write_req | cube_sc_pmu_read_l0a_instr、pmu_wr_l0a_instr、cube_sc_pmu_read_l0b_instr、pmu_wr_l0b_instr、fixp_rd_l0c_instr、cube_sc_pmu_read_l0c_instr、cube_sc_pmu_write_l0c_instr |
6资源冲突率 | bankgroup_stall_cycles、bank_stall_cycles、vec_resc_conflict_cycles | stu_pmu_wctl_ub_cflt、ldu_pmu_ib_ub_cflt、pmu_idc_aic_vec_instr_vf_busy_o、idu_pmu_ins_iss_cnt |
7UB 带宽 | ub_read_bw_mte、l2_write_bw、main_mem_write_bw、ub_write_bw_mte、ub_read_bw_vector、ub_write_bw_vector、ub_read_bw_scalar、ub_write_bw_scalar | pmu_rd_acc_ub_instr_p、pmu_wr_acc_ub_instr_p、pmu_fix_wr_ub_instr、mte_sc_pmu_write_acc_ub_instr_0、mte_sc_pmu_read_acc_ub_instr_0、ub_pmu_vec_rd_ub_acc、ub_pmu_vec_wr_ub_acc |
8L2 缓存 | write_cache_hit、write_cache_miss_allocate、r0_read_cache_hit、r0_read_cache_miss_allocate、r1_read_cache_hit、r1_read_cache_miss_allocate | bif_sc_pmu_ar_close_l2_hit_core、bif_sc_pmu_ar_close_l2_miss_core、bif_sc_pmu_ar_close_l2_victim_core、bif_sc_pmu_aw_close_l2_hit_core、bif_sc_pmu_aw_close_l2_miss_core、bif_sc_pmu_aw_close_l2_victim_core |
注意:上表中 dav_2201 的
5号事件组在解析脚本中存在 l0a_read_req 重复列名的写法,实际含义分别为 L0A 读请求与 L0A 写请求,解析结果以脚本实际输出列名为准。
环境变量的生效机制与默认值回退
从 pmu_common.cpp 的PmuCommon::InitPmuEventType可以看到环境变量的处理逻辑:
- 通过
GetEnvVar("PYPTO_PROF_PMU_EVENT_TYPE")读取环境变量; - 若环境变量未设置(字符串为空),打印告警日志 "Don't support PYPTO_PROF_PMU_EVENT_TYPE env, use default pmu event type PIPE_UTILIZATION.",并回退使用默认事件组
PIPE_UTILIZATION(取值为2); - 若环境变量值无法被解析为整数(
std::stoi抛出异常),同样打印告警并回退到默认事件组2; - 若解析出的整数不在
[1, 2, 4, 5, 6, 7, 8]范围内,SetPmuEventTypeDAV2201/SetPmuEventTypeDAV3510的 default 分支会打印告警 "Invalid profPmuType %d, only support [1,2,4,5,6,7,8].",此时pmuEvtType保持全0x0初始值; - 事件组长度依据架构确定:DAV2201 固定 8 个事件槽位、DAV3510 固定 10 个事件槽位,未用到的事件槽位以
0x0填充。
因此在实际使用中,建议显式设置环境变量为受支持取值,避免依赖默认回退或产生无效事件组。
完整实操流程:配置、采集与解析
步骤 1:选择采集模式(设置环境变量)
export PYPTO_PROF_PMU_EVENT_TYPE=2将取值替换为1、2、4、5、6、7、8中的任意一个即可切换采集主题。以下图片展示了各取值对应的事件组模式(图片来源:PMU_event.png):
PMU支持的模式
步骤 2:使用 msprof 采集 PMU 数据
设置环境变量后,在运行 PyPTO 算子脚本时通过msprof命令开启采集:
# 采集PMU数据 msprof --task-time=l3 --output=./prof_data python xxx.py其中:
--task-time=l3:开启 PMU 采集开关,l3表示任务级(Task Time)三级采集;--output:指定 PROF 产物的输出路径,默认落盘在当前工作目录下。
PMU 数据采集完成后,会落盘在output/PROF*/device_*/data/目录下(PROF_xxx/device_x/data)。
步骤 3:解析 PMU 数据为 CSV
# 解析数据 python tools/profiling/tilefwk_pmu_to_csv.py -p PROF_xxx/device_x/data -pe=$PYPTO_PROF_PMU_EVENT_TYPE --arch dav_3510解析脚本 tilefwk_pmu_to_csv.py 支持的参数如下:
| 参数 | 说明 | 默认值 |
|---|---|---|
-p, --path | 待解析的绝对路径,即包含aicpu.data*文件的 data 目录 | 必填 |
-pe, --pmuEvent | PMU 事件组编号,choices=[1, 2, 4, 5, 6, 7, 8],与PYPTO_PROF_PMU_EVENT_TYPE保持一致 | 2 |
--arch | 芯片架构类型,choices=['dav_2201', 'dav_3510'],决定使用哪套事件列名表与事件数 | dav_2201 |
--output | PMU 数据 CSV 存储路径,为空时生成到当前目录下的tilefwk_prof_pmu.csv | 当前目录 |
解析完成后,会在指定的输出目录(默认项目根目录)下生成tilefwk_prof_pmu.csv文件,其中包含thread id、task id、stream id、core id、seqNo、sub task id、total cycle等公共列,以及所选事件组对应的各 PMU 计数列。
架构参数与事件数匹配:解析脚本在 tilefwk_pmu_to_csv.py 中根据--arch与-pe选择事件列名,并依据二进制记录中实际携带的计数器数量截断/补充列头。因此--arch必须与实际运行芯片架构一致,否则列名与数据无法正确对应。
步骤 4:分析 CSV 结果
生成的 CSV 可通过任意表格工具或 pandas 打开。以默认事件组2(流水线利用率)为例,dav_3510 架构下会输出各任务的cube_instr_busy、scalar_instr_busy、mte1/2/3_instr_busy等列,开发者可以据此判断 AI Core 上各硬件流水线的忙碌程度,找出计算密集或搬运等待的瓶颈阶段。
测试与工具链中的典型用法
仓库中已有对该环境变量的自动化使用与验证:
- test_profiling.py 在 ST 测试中通过
int(os.environ.get("PYPTO_PROF_PMU_EVENT_TYPE", "2"))读取事件组,并依据pypto.platform.npuarch自动选择dav_3510/dav_2201架构,随后调用 tilefwk_pmu_to_csv.py 完成解析并校验 CSV 中 PMU 计数值非全零; - test_device_runner.cpp 在单元测试中循环设置
PYPTO_PROF_PMU_EVENT_TYPE并断言事件组初始化符合预期; - work_flow.py 在 PMU 数据工作流脚本中会将
PYPTO_PROF_PMU_EVENT_TYPE注入子进程环境变量,用于配套的 Profiling 数据解析与绘图流程。
这些示例印证了"设置环境变量 → 采集 → 解析 → 分析"的标准链路,也便于开发者将 PMU 采集能力集成到自己的脚本或 CI 流程中。
使用约束
- 完整的 PMU 采集流程详见性能调优文档中"采集PMU数据"章节,该章节还介绍了泳道图采集、PMU Trace 核内流水分析等其他性能调优手段,建议配合使用;
- 环境变量只在支持 PMU 采集的硬件与 Profiling 组件环境下生效,
msprof工具需随 CANN 环境正常配置; - 事件组编号与硬件架构强相关,跨架构移植脚本时请同步核对
--arch参数与事件列名含义; - 若需针对核内流水做深度分析(MTE2/MTE3/Vector/Cube 时序排布),可进一步开启 PMU Trace(
enable_pmu_trace),其与本文的 PMU 事件组采集属于不同能力,详见性能调优文档。
产品支持情况
PYPTO_PROF_PMU_EVENT_TYPE 支持的产品如下:
- Ascend 950PR / Ascend 950DT:支持
- Atlas A3训练系列产品 / Atlas A3推理系列产品:支持
- Atlas A2训练系列产品 / Atlas A2推理系列产品:支持
小结
PYPTO_PROF_PMU_EVENT_TYPE 以极简的整数取值抽象了 AI Core 上复杂的 PMU 寄存器事件配置,覆盖算数利用率、流水线利用率、内存访问、L0 缓存、资源冲突、UB 带宽、L2 缓存七大主题,并通过运行时按架构自动映射事件 ID,使开发者只需"选主题、设变量、跑 msprof、解析 CSV"即可获得结构化的硬件性能数据。结合 pmu_common.cpp 的事件组定义与 tilefwk_pmu_to_csv.py 的列名映射,开发者可以快速定位算子在 AI Core 上的瓶颈所在,为后续 TileShape、Stitch、合图等调优手段提供数据依据。
【免费下载链接】pyptoPyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。项目地址: https://gitcode.com/cann/pypto
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考