CANN学习资源开源仓的算子调试三msProf及仿真
使用CANN包自带msProf上板模式抓取单算子API调用程序执行时算子的性能数据。
| 参数名 | 作用 |
--kernel-name |
要采集的算子名称,支持使用算子名前缀进行模糊匹配。如果不指定,则只对程序运行过程中调度的第一个算子进行采集。 |
--launch-count |
可以采集算子的最大数量,默认值为1,取值范围为1~5000之间的整数。 |
--launch-skip-before-match |
不需要采集数据的算子数量,从第一个算子开始到指定数目的算子不进行采集,仅对指定数目之后的算子开始采集。 |
--warm-up |
部分算子使用 msprof op 采集时,会达不到芯片提频的最小任务耗时产生降频,从而会对交付件的结果产生一定影响。在该情况下,可用 --warm-up 指定预热次数,提前提升AI处理器的运行频率,使上板数据更准确。 |
--output |
收集到的性能数据的存放路径,默认在当前目录下保存性能数据。 |
采集命令:
msprof op --output=Sources/08.02/prof ./execute_op
输出
2026-04-02 15:44:10 [INFO] Performance Summary Report:
1) MTE2 bandwidth utilization lower than 80% when active.
2) MTE3 bandwidth utilization lower than 80% when active.
3) aivector compute usage lower than 20%.
2026-04-02 15:44:10 [INFO] Operator Basic Information:
Op Name: AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2_0
Op Type: vector
Task Duration(us): 20.080402
Block Dim: 8
Mix Block Dim:
Device Id: 0
Pid: 1425
Current Freq: 1650
Rated Freq: 1650
2026-04-02 15:44:10 [INFO] Profiling results saved in /opt/atomgit/cann-learning-hub/tutorials/ascendc_operator_development/08_performance_optimization/Sources/08.02/prof/OPPROF_20260402154402_RODXHPXLWWXRTIHH
2026-04-02 15:44:10 [INFO] Profiling data parse finished.
2026-04-02 15:44:10 [INFO] Op profiling finish. Welcome to next use.
# 输出目录 OPPROF_20260402154402_RODXHPXLWWXRTIHH
├── visualize_data.bin // 算子基础信息、计算单元负载、热点函数和Roofline瓶颈分析等信息的可视化呈现文件
├── OpBasicInfo.csv // 算子基础信息,包含算子名称、block dim和耗时等信息
├── ResourceConflictRatio.csv // UB上的bank group、bank conflict和资源冲突在所有指令中的占比
├── PipeUtilization.csv // 采集计算单元和搬运单元耗时和占比
├── Memory.csv // UB/L1/L2/主存储器采集内存读写带宽速率
├── L2Cache.csv // L2 Cache命中率
├── MemoryL0.csv // L0A/L0B/L0C采集内存读写带宽速率
├── dump/ // 原始的性能数据文件夹,用户无需关注
├── ArithmeticUtilization.csv // Cube和Vector类型的指令耗时和占比
└── MemoryUB.csv // mte/vector/scalar采集ub读写带宽速率
搬运相关流水理论耗时(MTE1/MTE2/MTE3等)
计算公式:
搬运数据量(单位:Byte) / 理论带宽
示例:
某款AI处理器的GM峰值带宽约为1.8TB/s,想要进行一次float数据类型、4096 * 4096大小的矩阵搬运,搬运的理论耗时是:
sizeof(float) * 4096 * 4096 / 1.8TB/s = 37.28us(按照1TB = 10^12 Byte来计算)
- 搬运指令同时存在时,会存在共享带宽的情况,并不能每条都以接近理论带宽的速率搬运数据。例如,当MTE2/MTE3同时进行GM读写时,搬运流水线的耗时应该是(MTE2搬运量 + MTE3搬运量)/ GM带宽。
- 搬运不同大小的数据块时,对带宽的利用率(有效带宽/理论带宽)不一样。针对每次搬运数据量较小的情况,实测性能达不到理论带宽。
计算相关流水理论耗时(Cube/Vector/Scalar等)
计算公式:
计算数据量(单位:Element) / 理论算力
示例:
某款AI处理器对float数据类型的Vector理论峰值算力为11.06TOPS,想要进行一次32K float类型的Element单指令计算,计算的理论耗时是:
32K / 11.06TOPS = 0.003us(按照1K = 1000来计算)
耗时较长的流程、实际数值与理论数值差异较大的环节,均被判定为性能“瓶颈点”。性能数据的指标查看:
| 字段名称 | 字段说明 |
|---|---|
| block_id | Task运行切分数量,对应Task运行时配置的核数。 |
| sub_block_id | Task运行使用的每个block名称和序号。 |
| aiv_time(us) | 该Task被分配到每个AI Vector Core计算单元上后,每个AI Vector Core计算单元上的执行时间,单位us。 |
| aiv_total_cycles | 该Task被分配到每个AI Vector Core计算单元上后,每个AI Vector Core计算单元上的执行的cycle总数。 |
| aiv_vec_time(us) | 代表vec类型指令(向量类运算指令)耗时。 |
| aiv_vec_ratio | 代表vec类型指令(向量类运算指令)的cycle数在total cycle数中的占用比。 |
| aiv_scalar_time(us) | 代表scalar类型指令(标量类运算指令)耗时。 |
| aiv_scalar_ratio | 代表scalar类型指令(标量类运算指令)的cycle数在total cycle数中的占用比。 |
| aiv_mte2_time(us) | 代表MTE2类型指令(GM->AICORE搬运类指令)耗时。 |
| aiv_mte2_ratio | 代表MTE2类型指令(GM->AICORE搬运类指令)的cycle数在total cycle数中的占用比。 |
| aiv_mte3_time(us) | 代表MTE3类型指令(AICORE->GM搬运类指令)耗时。 |
| aiv_mte3_ratio | 代表MTE3类型指令(AICORE->GM搬运类指令)的cycle数在total cycle数中的占用比。 |
| aiv_icache_miss_rate | 代表ICache缺失率,即未命中instruction的L1 cache,数值越小越好。 |
| aiv_mte3_active_bw(GB/s) | 代表MTE3类型指令(AICORE->DDR AIV搬运类指令)数据量对应active cycle的活跃带宽。 |
| aiv_mte2_active_bw(GB/s) | 代表MTE2类型指令(DDR->AICORE AIV搬运类指令)数据量对应active cycle的活跃带宽。 |
示例代码没有开启DOUBLE BUFFER,所以在profiling数据中,所有耗时为搬入耗时 + 运算耗时 + 搬出耗时,需要关注aiv_time(us)、aiv_scalar_time(us)、aiv_mte2_time(us)、aiv_vec_time(us)、aiv_mte3_time(us)的耗时。从PipeUtilization.csv的性能数据表格中,我们可以看到scalar占比超过了90%,那么scalar运算耗时为重点优化对象。查看Kernel侧实现,scalar运算有三部分内容:
- Init函数内对tileLength的长度计算和对x、y、z的GlobalMemory偏移计算。
- Process函数的循环控制和printf打印。
- CopyIn、CopyOut函数内的地址偏移计算。
只有第一部分的tileLength计算可以放到host侧进行,第二部分的printf打印可以屏蔽。其他部分代码需要保持原来的实现,不能放到host侧进行。而tilingLength计算量较小,不会对性能造成较大影响,所以推测将printf打印屏蔽后,算子的性能会有较大提升。结果也如是。
相对于msProf上板,仿真模式多了一个参数simulator,指定仿真的产品型号,并在op_kernel的CMakeLists.txt中增加允许调试选项(用于仿真查看源码),末尾增加一行
npu_op_kernel_options(ascendc_kernels ALL OPTIONS -g)
然后根据仿真产品型号设置环境变量,以仿真Atlas A2训练产品为例:
export LD_LIBRARY_PATH=${ASCEND_TOOLKIT_HOME}/tools/simulator/Ascend910B1/lib:$LD_LIBRARY_PATH
使用msprof op simulator抓取执行的仿真性能:
msprof op simulator --output=./output_data ./xxxx
如果不设置LD_LIBRARY_PATH,也可通过增加–soc-version指定要仿真的产品型号:
msprof op simulator --soc-version=Ascend910B1 --output=./output_data ./xxxx
如果确认核间数据为均匀分布,或者只想获取指定核的仿真数据,可以通过–core-id来指定核。以采集id为0的核的仿真性能为例:
msprof op simulator --soc-version=Ascend910B1 --output=./output_data --core-id=0 ./xxxx
#实际运行例子
source ${HOME}/vendors/customize/bin/set_env.bash;msprof op simulator --soc-version=Ascend910B1 --output=./Sources/08.03/prof --core-id=0 ./Sources/08.03/execute_op
输出
2026-04-02 19:06:07 [INFO] Core operator results run in simulator as follow:
core_name duration_time(us) running_time(us)
core0.veccore0 33.19 32.33
2026-04-02 19:06:10 [INFO] Profiling running finished. All task success.
2026-04-02 19:06:10 [INFO] Start parse dump file
2026-04-02 19:06:10 [INFO] Profiling results saved in /opt/atomgit/cann-learning-hub/tutorials/ascendc_operator_development
/08_performance_optimization/Sources/08.03/prof/OPPROF_20260402190529_CZOKFVMRLHFFTJWQ
2026-04-02 19:06:10 [INFO] Profiling data parse finished.
2026-04-02 19:06:10 [INFO] Op profiling finish. Welcome to next use.
# 输出目录 OPPROF_20260402190529_CZOKFVMRLHFFTJWQ
├── simulator/
│ ├── core0.veccore0/ // 按照core*.veccore*或core*.cubecore*目录存放各核的数据文件
│ ├── trace.json // 全部核或指定核的仿真指令流水图文件
│ └── visualize_data.bin // 全部核或指定核的仿真指令流水图文件、insight使用
└── dump/ // 存放过程件的文件夹,无需关注
├── aicore_binary.o
├── object_dump.txt
└── pc_start_addr.txt
借助Chrome浏览器的chrome://tracing打开trace.json或者使用mindstudio insight打开trace.json、visualize_data.bin。二者时间线界面基本一致,但insight切换到源码界面,在设置好对应源码后,可查看每行代码对应的时钟周期,更直观的看到耗时较多的代码或代码块。本例中,算子整体耗时中MTE2、VECTOR、MET3耗时均很短,而SCALAR运算耗时很长,点击右侧SCALAR可在下方看到该流水任务对应的具体代码行数,如下:
/usr/local/Ascend/cann-8.5.0/aarch64-linux/asc/impl/basic_api/dav_c220/kernel_operator_dump_tensor_impl.h:1074
/usr/local/Ascend/cann-8.5.0/aarch64-linux/asc/impl/basic_api/kernel_operator_dump_tensor_intf_impl.h:167
#下面2个文件是我们编码的文件
/opt/atomgit/cann-learning-hub/tutorials/ascendc_operator_development/08_performance_optimization/Sources/08.03/custom_op/op_kernel/add_custom_template.cpp:42
/opt/atomgit/cann-learning-hub/tutorials/ascendc_operator_development/08_performance_optimization/Sources/08.03/custom_op/op_kernel/add_custom_template.cpp:92
#下面2个文件是中间临时文件,事后无法查看
/opt/atomgit/cann-learning-hub/tutorials/ascendc_operator_development/08_performance_optimization/Sources/08.03/custom_op/build_out/op_kernel/AddCustomTemplate_ascend910b/kernel_1/kernel_meta_AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2/kernel_meta/AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2_2940_kernel.cpp:54
/opt/atomgit/cann-learning-hub/tutorials/ascendc_operator_development/08_performance_optimization/Sources/08.03/custom_op/build_out/op_kernel/AddCustomTemplate_ascend910b/kernel_1/kernel_meta_AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2/kernel_meta/AddCustomTemplate_862645f6bafeab7b8e397662e7e517c2_2940_kernel.cpp:59



- 点赞
- 收藏
- 关注作者
评论(0)