应用调试
Profiling性能数据采集
基本原理
该章节下的接口用于Profiling采集性能数据,实现方式支持以下三种:
Profiling pyACL API(通过Profiling pyACL API采集并落盘性能数据):实现将采集到的Profiling数据写入文件,再使用Profiling工具解析该文件(请参见《性能分析工具使用指南》下的“数据解析与导出”),并展示性能分析数据。
包括以下两种接口调用方式:
-
acl.prof.init接口、acl.prof.start接口、acl.prof.stop接口、acl.prof.finalize接口配合使用,实现该方式的性能数据采集。该方式可获取pyACL的接口性能数据、AI Core上算子的执行时间、AI Core性能指标数据等。目前这些接口为进程级控制,表示在进程内任意线程调用该接口,其它线程都会生效。
一个进程内,可以根据需求多次调用这些接口,基于不同的Profiling采集配置,采集数据。
-
调用acl.init接口,在pyACL初始化阶段,通过*.json 文件传入要采集的Profiling数据。该方式可获取pyACL的接口性能数据、AI Core上算子的执行时间、AI Core性能指标数据等。
一个进程内,只能调用一次acl.init接口,如果要修改Profiling采集配置,需修改*.json文件中的配置。详细使用说明请参见acl.init接口处的说明,不在本章节描述。
Profiling pyACL API for Extension(Profiling pyACL API扩展接口):当用户需要定位应用程序或上层框架程序的性能瓶颈时,可在Profiling采集进程内(acl.prof.start接口、acl.prof.stop接口之间)调用Profiling pyACL API扩展接口(统称为msproftx功能),开启记录应用程序执行期间特定事件发生的时间跨度,并将数据写入Profiling数据文件,再使用Profiling工具解析该文件,并导出展示性能分析数据。
Profiling工具解析导出操作请参见《性能分析工具使用指南》下的“Profiling数据解析”和“Profiling数据导出”。
一个进程内,可以根据需求多次调用这些接口。
接口调用方式:在acl.prof.start和acl.prof.stop接口之间调用acl.prof.create_stamp、acl.prof.push、acl.prof.pop、acl.prof.range_start、acl.prof.range_stop、acl.prof.destroy_stamp接口。该方式可获取应用程序执行期间特定时间发生的事件并记录事件发生的时间跨度。
一个进程内,可以根据需求多次调用这些接口。
Profiling pyACL API for Subscription(订阅算子信息的Profiling pyACL API):实现将采集到的Profiling数据解析后写入管道,由用户读入内存,再由用户调用pyACL的接口获取性能数据。
接口调用方式:acl.prof.model_subscribe接口、acl.prof.get*接口、acl.prof.model_unsubscribe接口配合使用,实现该方式的性能数据采集,当前支持获取网络模型中算子的性能数据,包括算子名称、算子类型名称、算子执行时间等。
Profiling pyACL API示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
示例中,运行管理资源申请与释放请参见运行管理资源申请流程与运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构。
<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40<br>41<br>42<br>43<br>44<br>45<br>46<br>47<br>48<br> | python<br>import acl<br>import numpy as np<br># ......<br># 1.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream。<br># ......<br># 2.模型加载,加载成功后,返回标识模型的model_id。<br># ......<br># 3.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output。<br># ......<br># 4.profiling初始化。<br># 设置数据落盘路径。<br>PROF_INIT_PATH='...'<br>ret = acl.prof.init(PROF_INIT_PATH)<br># 5.进行profiling配置。<br>device_list = [0]<br>ACL_PROF_ACL_API = 0x0001<br>ACL_PROF_TASK_TIME = 0x0002<br>ACL_PROF_AICORE_METRICS = 0x0004<br>ACL_PROF_AICPU_TRACE = 0x0008<br>ACL_PROF_SYS_HARDWARE_MEM_FREQ = 3<br># 创建配置类型指针地址。<br>prof_config = acl.prof.create_config(device_list, 0, 0, ACL_PROF_ACL_API | ACL_PROF_TASK_TIME | ACL_PROF_AICPU | ACL_PROF_AICORE_METRICS | ACL_PROF_HCCL_TRACE)<br>mem_freq = "15"<br>ret = acl.prof.set_config(ACL_PROF_SYS_HARDWARE_MEM_FREQ, mem_freq)<br>ret = acl.prof.start(prof_config)<br># 6.执行模型。<br>ret = acl.mdl.execute(model_id, input, output)<br># 7.处理模型推理结果。<br># ......<br># 8.释放描述模型输入/输出信息、内存等资源,卸载模型。<br># ......<br># 9.关闭profiling配置, 释放配置资源, 释放profiling组件资源。<br>ret = acl.prof.stop(prof_config)<br>ret = acl.prof.destroy_config(prof_config)<br>ret = acl.prof.finalize()<br># 10.释放运行管理资源<br># ......<br> |
|---|
Profiling pyACL API for Extension示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
示例中,运行管理资源申请与释放请参见运行管理资源申请流程与运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构。
for i in range(200000):
stamp = acl.prof.create_stamp()
if stamp == 0:
print("create stamp failed")
return FAILED
msg = "test msprof tx"
msg_len = len(msg)
ret = acl.prof.set_stamp_trace_message(stamp, msg, msg_len)
ret = acl.prof.mark(stamp)
ret = acl.prof.destroy_stamp(stamp)
或
for i in range(200000):
stamp = acl.prof.create_stamp()
if stamp == 0:
print("create stamp failed")
return FAILED
msg = "test msprof tx"
msg_len = len(msg)
ret = acl.prof.set_stamp_trace_message(stamp, msg, msg_len)
## acl.prof.push 和 acl.prof.pop 接口配对使用,完成单线程采集
ret = acl.prof.push(stamp)
ret = acl.prof.pop()
ret = acl.prof.destroy_stamp(stamp)
或
for i in range(200000):
stamp = acl.prof.create_stamp()
if stamp == 0:
print("create stamp failed")
return FAILED
msg = "test msprof tx"
msg_len = len(msg)
ret = acl.prof.set_stamp_trace_message(stamp, msg, msg_len)
## acl.prof.range_start 和 acl.prof.range_stop 接口配对使用,可以完成多线程采集
range_id = 0
range_id, ret = acl.prof.range_start(stamp)
ret = acl.prof.range_stop(range_id)
ret = acl.prof.destroy_stamp(stamp)
Profiling pyACL API for Subscription示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
示例中,运行管理资源申请与释放请参见运行管理资源申请流程与运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构。
<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40<br>41<br>42<br>43<br>44<br>45<br>46<br>47<br>48<br>49<br>50<br>51<br>52<br>53<br>54<br>55<br>56<br>57<br>58<br>59<br>60<br>61<br>62<br>63<br>64<br>65<br>66<br>67<br>68<br>69<br>70<br>71<br>72<br>73<br>74<br>75<br>76<br>77<br>78<br>79<br>80<br>81<br>82<br>83<br>84<br>85<br> | python<br>import acl<br>import numpy as np<br># ......<br># 1.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream。<br># ......<br># 2.模型加载,加载成功后,返回标识模型的model_id。<br># ......<br># 3.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output。<br># ......<br># 4.创建管道,用于读取以及写入模型订阅的数据。<br>r, w = os.pipe()<br># 5.创建模型订阅的配置并且进行模型订阅。<br>ACL_AICORE_NONE = 0xFF<br>subscribe_config = acl.prof.create_subscribe_config(1, ACL_AICORE_NONE, w)<br># 模型订阅需要传入模型的model_id。<br>ret = acl.prof.model_subscribe(model_id, subscribe_config)<br># 6.实现管道读取订阅数据的函数。<br># 6.1 自定义函数,实现从用户内存中读取订阅数据的函数。<br>def get_model_info(data, data_len):<br> # 获取算子信息个数。<br> op_number, ret = acl.prof.get_op_num(data, data_len)<br> # 遍历用户内存的算子信息。<br> for i in range(op_number):<br> # 获取算子的模型id。<br> model_id = acl.prof.get_model_id(data, data_len, i)<br> # 获取算子的类型名称。<br> op_type, ret = acl.prof.get_op_type(data, data_len, i, 65)<br> # 获取算子的名称。<br> op_name, ret = acl.prof.get_op_name(data, data_len, i, 275)<br> # 获取算子的执行开始时间。<br> op_start = acl.prof.get_op_start(data, data_len, i)<br> # 获取算子的执行结束时间。<br> op_end = acl.prof.get_op_end(data, data_len, i)<br> # 获取算子执行的耗时时间。<br> op_duration = acl.prof.get_op_duration(data, data_len, i)<br># 6.2 自定义函数,实现从管道中读取数据到用户内存的函数。<br>def prof_data_read(args):<br> fd, ctx = args<br> ret = acl.rt.set_context(ctx)<br> # 获取单位算子信息的大小(Byte)。<br> buffer_size, ret = acl.prof.get_op_desc_size()<br> # 设置每次从管道中读取的算子信息个数。<br> N = 10<br> # 计算存储算子信息的内存的大小。<br> data_len = buffer_size * N<br> # 从管道中读取数据到申请的内存中,读取到的实际数据大小可能小于buffer_size * N,如果管道中没有数据,默认会阻塞直到读取到数据为止。<br> while True:<br> data = os.read(fd, data_len)<br> if len(data) == 0:<br> break<br> np_data = np.array(data)<br> <br> bytes_data = np_data.tobytes()<br> np_data_ptr = acl.util.bytes_to_ptr(bytes_data)<br> size = np_data.itemsize * np_data.size<br> # 调用6.1实现的函数解析内存中的数据。<br> get_model_info(np_data_ptr, size)<br># 7.启动线程读取管道数据并解析。<br>thr_id, ret = acl.util.start_thread(prof_data_read, [r, context])<br># 8.执行模型。<br>ret = acl.mdl.execute(model_id, input, output)<br># 9.处理模型推理结果。<br># ......<br># 10.释放描述模型输入/输出信息、内存等资源,卸载模型。<br># ......<br># 11.取消订阅,释放订阅相关资源。<br>ret = acl.prof.model_unsubscribe(model_id)<br>ret = acl.util.stop_thread(thr_id)<br>os.close(r)<br>ret = acl.prof.destroy_subscribe_config(subscribe_config)<br># 12.释放运行管理资源。<br># ......<br> |
|---|
父主题: 扩展更多特性
溢出算子数据采集及分析
前提条件
使用ATC工具转换模型时,需在转换命令中增加“--status_check”参数,并将参数值设置为“1”,表示在编译算子时添加溢出检测逻辑。
关于ATC工具及其参数的详细说明,请参见《ATC工具使用指南》。
采集溢出算子信息
在调用调用acl.init接口初始化pyACL时,在JSON配置文件中增加溢出算子Dump配置。
JSON配置文件中的示例内容如下,示例中的“dump_path”以相对路径为例:
{
"dump":{
"dump_path":"output",
"dump_debug":"on"
}
}
当dump_path配置为相对路径时,您可以在“应用可执行文件的目录/{dump_path}”下查看导出的数据文件,针对每个溢出算子,会导出两个数据文件:
-
溢出算子的dump文件:命名规则如{op_type}.{op_name}.{taskid}.{stream_id}.{timestamp},如果op_type、op_name出现了“.”、“/”、“\”、空格时,会转换为下划线表示。
用户可通过该信息知道具体出现溢出错误的算子,并通过解析溢出算子的dump文件获取该算子的输入和输出信息。
-
算子溢出数据文件:命名规则如OpDebug.Node_Opdebug.{taskid}.{stream_id}.{timestamp},其中taskid不是溢出算子的taskid,用户不需要关注taskid的实际含义。
用户可通过解析算子溢出数据文件获取溢出相关信息,包括溢出算子所在的模型、AICore的status寄存器状态等。
解析溢出算子的dump文件
-
请根据实际情况,将{op_type}.{op_name}.{taskid}.{stream_id}.{timestamp}上传到安装有Toolkit软件包的环境。
-
进入解析脚本所在目录,例如Toolkit软件包安装目录为:/home/HwHiAiUser/Ascend/ascend-toolkit/latest。
cd /home/HwHiAiUser/Ascend/ascend-toolkit/latest/toolkit/tools/operator_cmp/compare -
执行msaccucmp.py脚本,转换dump文件为numpy文件。举例:
python3 msaccucmp.py convert -d /home/HwHiAiUser/dump -out /home/HwHiAiUser/dumptonumpy -v 2:::note 说明 -d参数支持传入单个文件,对单个dump文件进行转换,也支持传入目录,对整个path下所有的dump文件进行转换。 :::
-
调用Python,转换numpy文件为txt文件。举例:
$ python3>>> import numpy as np>>> a = np.load("/home/HwHiAiUser/dumptonumpy/Pooling.pool1.1147.1589195081588018.output.0.npy")>>> b = a.flatten()>>> np.savetxt("/home/HwHiAiUser/dumptonumpy/Pooling.pool1.1147.1589195081588018.output.0.txt", b)转换为.txt格式文件后,维度信息、Dtype均不存在。详细的使用方法请参考numpy官网介绍。
解析算子溢出数据文件
由于生成的溢出数据是二进制格式,可读性较差,需要通过工具将bin文件解析为用户可读性好的JSON文件。
-
请根据实际情况,将溢出数据文件OpDebug.Node_Opdebug.{taskid}.{timestamp}上传到安装有Toolkit软件包的环境。
-
进入解析脚本所在路径,例如Toolkit软件包安装目录为:/home/HwHiAiUser/Ascend/ascend-toolkit/latest。
cd /home/HwHiAiUser/Ascend/ascend-toolkit/latest/toolkit/tools/operator_cmp/compare -
执行解析命令,例如:
python3 msaccucmp.py convert -d /home/HwHiAiUser/opdebug/Opdebug.Node_OpDebug.59.1597922031178434 -out /home/HwHiAiUser/result关键参数:
- -d:溢出数据文件所在目录,包括文件名。
- -out:解析结果待存储目录,如果不指定,默认生成在当前目录下。
-
解析结果文件内容如下所示。
{"DHA Atomic Add": {"model_id": 0,"stream_id": 0,"task_id": 0,"task_type": 0,"pc_start": "0x0","para_base": "0x0","status": 0},"L2 Atomic Add": {"model_id": 0,"stream_id": 0,"task_id": 0,"task_type": 0,"pc_start": "0x0","para_base": "0x0","status": 0},"AI Core": {"model_id": 514,"stream_id": 563,"task_id": 57,"task_type": 0,"pc_start": "0x1008005b0000","para_base": "0x100800297000","kernel_code": "0x1008005ae000","block_idx": 1,"status": 32}}参数解释:
-
model_id:标识溢出算子所在的模型id。
-
stream_id:标识溢出算子所在的streamid。
-
task_id:标识溢出算子的taskid。
-
task_type:标识溢出算子的task类型。
-
pc_start:标识溢出算子的代码程序的内存起始地址。
-
para_base:标识溢出算子的参数的内存起始地址。
-
kernel_code:标识溢出算子的代码程序的内存起始地址,和pc_start相同。
-
block_idx:标识溢出算子的blockid参数。
-
status:AICore的status寄存器状态,用户可以从status值分析得到具体溢出错误。status为10进制表示,需要转换成16进制,然后定位到具体错误。
例如:status为272,转换成16进制为0x00000110,则可以判定出可能原因为0x00000010+0x00000100。
- 0x00000008:符号整数最小负数NEG符号位取反溢出。
- 0x00000010:整数加法、减法、乘法或乘加操作计算有溢出。
- 0x00000020:浮点计算有溢出。
- 0x00000080:浮点数转无符号数的输入是负数。
- 0x00000100:FP32转FP16或32位符号整数转FP16中出现溢出。
- 0x00000400:CUBE累加出现溢出。
-
父主题: 扩展更多特性
应用调试
运行应用
运行应用的步骤,请参考基于Caffe ResNet-50网络实现图片分类(同步推理)。
相关注意点如下:
-
模型转换,详细说明请参见《ATC工具使用指南》。
-
运行时,需将pyACL初始化配置文件(acl.json)所在的目录、测试图片所在的目录、*.om文件所在的目录都上传到Host的同一个目录下。
如果在pyACL初始化阶段,在acl.init接口中不传入参数,则无需将pyACL初始化配置文件(acl.json)所在的目录上传到Host。
-
运行代码时,直接运行对应的Python脚本即可。如:
python3 main.py
问题定位
运行应用时如果出错,您可以参见《日志参考》获取日志文件,以便查看日志文件中详细报错。根据报错初步定位后:
- 如果是接口约束导致接口调用逻辑不对,需查看总体的使用约束以及各接口本身的约束,再调整接口调用逻辑。
- 如果是算子在AI Core上运行报错,需要进一步定位算子报错的原因,可调用pyACL提供的接口,获取出错算子的描述信息,用于进一步分析时使用,可参见AI Core异常信息获取,查看原理及调用示例。
Python环境
前提条件
请参见表1完成环境准备。
表1 安装软件
名称 | 版本 | 说明 |
|---|---|---|
Python | Python3.7.5 | 安装方式与Python依赖版本的限制请参见《CANN 软件安装指南》。 |
Python3.8.0 ~ Python3.8.10 | ||
Python3.9.2 | ||
Python依赖 | - | |
Numpy | ≥ 1.18.2 | Python的一种开源的数值计算扩展。 使用pip3 install numpy安装Numpy。 |
Pillow | 7.2.0 | Python的图像处理库(Python Imaging Library)。 使用pip3 install Pillow命令安装Pillow。 |
:::note 说明 本节所列的python、pip命令,实际命名与用户机器中软链接设置的命名一致,以对应python3.7.5版本为示例,请用户自行替换。 :::
CentOS7 aarch64环境下安装Pillow的说明
CentOS7 aarch64环境中通过pip3.7 install Pillow安装Pillow之后,在执行from PIL import Image的时候会报错:
ImportError: /usr/local/python3.7.5/lib/python3.7/site-packages/PIL/_imaging.cpython-37m-aarch64-linux-gnu.so: ELF load command alignment not page-aligned
这种情况下,需要用源码安装Pillow。若已经通过pip安装,需要运行pip3.7 uninstall Pillow进行卸载。
-
在链接中获取Pillow的源码压缩包,以Pillow-7.2.0.tar.gz为例。
-
检查下列Pillow的依赖是否安装,如果没有安装则进行安装。
sudo yum install python-develsudo yum install zlib-develsudo yum install libjpeg-turbo-devel -
解压Pillow源码压缩包并进行编译安装。
tar -xvf Pillow-7.2.0.tar.gzcd Pillow-7.2.0/python3.7 setup.py buildpython3.7 setup.py install
父主题: 环境准备
准备环境
您需要部署开发环境和运行环境,请参见《CANN 软件安装指南》。
-
本文以如下安装路径示例来说明操作步骤,实际操作前,请务必获取这些组件的实际安装路径,以便后续操作时使用:
- 以HwHiAiUser用户安装Driver组件,Driver组件的默认安装路径为“${HOME}/Ascend”,在该路径下安装成功后,包括“driver”目录。
- 以HwHiAiUser用户安装cann-toolkit软件包,cann-toolkit软件包的默认安装路径为“${HOME}/Ascend”,在该路径下安装成功后,包括“ascend-toolkit”目录。
- 以HwHiAiUser用户安装cann-nnrt软件包,cann-nnrt软件包的默认安装路径为“${HOME}/Ascend”,在该路径下安装成功后,包括“nnrt”目录。
-
pyACL在cann-toolkit软件包、cann-nnrt软件包中均有集成,用户可根据使用场景自行选择其中之一进行安装。cann-toolkit软件包为开发套件包,适用于开发环境。cann-nnrt软件包为离线推理引擎包
-
本文以HwHiAiUser用户作为开发环境、运行环境的运行用户为例来说明操作步骤,实际操作前,请务必获取开发环境、运行环境的运行用户,以便后续操作时使用。
-
用户使用export命令在当前终端窗口下声明环境变量,关闭Shell终端或切换用户时环境变量失效。
父主题: 环境准备
环境变量配置
在安装完CANN软件包之后,请务必自行配置pyACL相关的环境变量,否则,将无法正常“import acl”。
-
若环境中安装了cann-toolkit软件包:
# 以root用户安装toolkit包。. /usr/local/Ascend/ascend-toolkit/set_env.sh# 以非root用户安装toolkit包。. ${HOME}/Ascend/ascend-toolkit/set_env.sh -
若环境中安装了cann-nnrt软件包:
# 以root用户安装nnrt包。. /usr/local/Ascend/nnrt/set_env.sh# 以非root用户安装nnrt包。. ${HOME}/Ascend/nnrt/set_env.sh
父主题: 环境准备
在线提单