应用调试
Profiling性能数据采集
基本原理
该章节下的接口用于Profiling采集性能数据,实现方式支持以下三种:
-
Profiling AscendCL API(通过Profiling AscendCL API采集并落盘性能数据)
实现将采集到的Profiling数据写入文件,再使用Profiling工具解析该文件(请参见《性能分析工具使用指南》下的“数据解析与导出”),并展示性能分析数据。
包括以下两种接口调用方式:
-
aclprofInit接口、aclprofStart接口、aclprofStop接口、aclprofFinalize接口配合使用,实现该方式的性能数据采集。该方式可获取AscendCL的接口性能数据、AI Core上算子的执行时间、AI Core性能指标数据等。目前这些接口为进程级控制,表示在进程内任意线程调用该接口,其它线程都会生效。
一个进程内,可以根据需求多次调用这些接口,基于不同的Profiling采集配置,采集数据。
-
调用aclInit接口,在AscendCL初始化阶段,通过*.json 文件传入要采集的Profiling数据。该方式可获取AscendCL的接口性能数据、AI Core上算子的执行时间、AI Core性能指标数据等。
一个进程内,只能调用一次aclInit接口,如果要修改Profiling采集配置,需修改*.json文件中的配置。详细使用说明请参见aclInit接口处的说明,不在本章节描述。
-
-
Profiling AscendCL API for Extension(Profiling AscendCL API扩展接口)
当用户需要定位应用程序或上层框架程序的性能瓶颈时,可在Profiling采集进程内(aclprofStart接口与aclprofStop接口之间)调用Profiling AscendCL API扩展接口(统称为msproftx功能),开启记录应用程序执行期间特定事件发生的时间跨度,并将数据写入Profiling数据文件,再使用Profiling工具解析该文件,并导出展示性能分析数据。
一个进程内,可以根据需求多次调用这些接口,接口调用方式如下:在aclprofStart和aclprofStop接口之间调用aclprofCreateStamp、aclprofPush、aclprofPop、aclprofRangeStart、aclprofRangeStop、aclprofDestroyStamp接口。该方式可获取应用程序执行期间特定时间发生的事件并记录事件发生的时间跨度。
Profiling工具解析导出操作请参见《性能分析工具使用指南》下的“Profiling数据解析”和“Profiling数据导出”。
-
Profiling AscendCL API for Subscription(订阅算子信息的Profiling AscendCL API)
实现将采集到的Profiling数据解析后写入管道,由用户读入内存,再由用户调用AscendCL的接口获取性能数据。
接口调用方式:aclprofModelSubscribe接口、aclprofGet*接口、aclprofModelUnSubscribe接口配合使用,实现该方式的性能数据采集,当前支持获取网络模型中算子的性能数据,包括算子名称、算子类型名称、算子执行时间等。
Profiling AscendCL API示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
本节中的示例重点介绍Profiling性能数据采集的代码逻辑,AscendCL初始化和去初始化请参见AscendCL初始化与去初始化,运行管理资源申请与释放请参见运行管理资源申请与释放,模型加载、准备模型推理的输入/输出数据的接口调用流程、模型执行、模型卸载等请参见模型推理。
<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> | <br>// 1.AscendCL初始化<br>// 2.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream<br>// 3.profiling初始化<br>// 设置数据落盘路径<br>const char *aclProfPath = "...";<br>aclprofInit(aclProfPath, strlen(aclProfPath));<br>// 4.进行profiling配置<br>uint32_t deviceIdList[1] = {0};<br>// 创建配置结构体<br>aclprofConfig *config = aclprofCreateConfig(deviceIdList, 1, ACL_AICORE_ARITHMETIC_UTILIZATION, <br> nullptr,ACL_PROF_ACL_API | ACL_PROF_TASK_TIME | ACL_PROF_AICORE_METRICS | ACL_PROF_AICPU | ACL_PROF_HCCL_TRACE | ACL_PROF_MSPROFTX | ACL_PROF_RUNTIME_API);<br>const char *memFreq = "15";<br>ret = aclprofSetConfig(ACL_PROF_SYS_HARDWARE_MEM_FREQ, memFreq, strlen(memFreq));<br>aclprofStart(config);<br>// 5.模型加载,加载成功后,返回标识模型的modelId<br>// 6.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output<br> <br>// 7.执行模型<br>ret = aclmdlExecute(modelId, input, output);<br>// 8.处理模型推理结果<br>// 9.释放描述模型输入/输出信息、内存等资源,卸载模型<br>// 10.关闭profiling配置, 释放配置资源, 释放profiling组件资源<br>aclprofStop(config);<br>aclprofDestroyConfig(config);<br>aclprofFinalize();<br>// 11.释放运行管理资源<br>// 12. AscendCL去初始化<br>// ......<br> |
|---|
Profiling AscendCL API for Extension示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
Profiling msproftx接口,请参见如下示例中的加粗部分代码。。
示例一(aclprofMark示例):
<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> | <br>//1.AscendCL初始化<br>//2.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream<br>stamp = aclprofCreateStamp();<br>aclprofSetStampTraceMessage(stamp, "aclrtCreateStream_mark", strlen("AscendCL_Init_Mark"));<br>aclprofMark(stamp); //标记Create Stream事件<br>aclprofDestroyStamp(stamp);<br>ret = aclrtCreateStream(&stream_);<br>//3..Profiling初始化<br>//设置数据落盘路径<br>const char *aclProfPath = "...";<br>aclprofInit(aclProfPath, strlen(aclProfPath));<br>//4.进行Profiling配置<br>uint32_t deviceIdList[1] = {0};<br>//创建配置结构体<br>aclprofConfig *config = aclprofCreateConfig(deviceIdList, 1, ACL_AICORE_ARITHMETIC_UTILIZATION, <br> nullptr,ACL_PROF_ACL_API | ACL_PROF_TASK_TIME);<br>const char *memFreq = "15";<br>ret = aclprofSetConfig(ACL_PROF_SYS_HARDWARE_MEM_FREQ, memFreq, strlen(memFreq));<br>aclprofStart(config);<br>aclprofStepInfo *stepInfo = aclprofCreateStepInfo();<br>int ret = aclprofGetStepTimestamp(stepInfo, ACL_STEP_START, stream_);<br>//5.模型加载,加载成功后,返回标识模型的modelId<br>stamp = aclprofCreateStamp();<br>aclprofSetStampTraceMessage(stamp, "model_load_mark", strlen("model_load_mark"));<br>aclprofMark(stamp); //标记模型加载事件<br>aclprofDestroyStamp(stamp);<br>//6.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output<br>//7.执行模型<br>ret = aclmdlExecute(modelId, input, output);<br>//8.处理模型推理结果<br>//9.释放描述模型输入/输出信息、内存等资源,卸载模型<br>int ret = aclprofGetStepTimestamp(stepInfo, ACL_STEP_END, stream_);<br>aclprofDestroyStepInfo(stepInfo);<br>//10.关闭Profiling配置, 释放配置资源, 释放Profiling组件资源<br>aclprofStop(config);<br>aclprofDestroyConfig(config);<br>aclprofFinalize();<br>//11.释放运行管理资源<br>//12. AscendCL去初始化<br>//......<br> |
|---|
示例二(aclprofPush/aclprofPop示例,适用于单线程):
<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> | <br>//1.AscendCL初始化<br>//2.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream<br>ret = aclrtCreateStream(&stream_);<br>//3..Profiling初始化<br>//设置数据落盘路径<br>const char *aclProfPath = "...";<br>aclprofInit(aclProfPath, strlen(aclProfPath));<br>//4.进行Profiling配置<br>uint32_t deviceIdList[1] = {0};<br>//创建配置结构体<br>aclprofConfig *config = aclprofCreateConfig(deviceIdList, 1, ACL_AICORE_ARITHMETIC_UTILIZATION, <br> nullptr,ACL_PROF_ACL_API | ACL_PROF_TASK_TIME);<br>const char *memFreq = "15";<br>ret = aclprofSetConfig(ACL_PROF_SYS_HARDWARE_MEM_FREQ, memFreq, strlen(memFreq));<br>aclprofStart(config);<br>aclprofStepInfo *stepInfo = aclprofCreateStepInfo();<br>int ret = aclprofGetStepTimestamp(stepInfo, ACL_STEP_START, stream_);<br>//5.模型加载,加载成功后,返回标识模型的modelId<br>//6.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output<br>//7.执行模型(模型仅在单线程执行)<br>stamp = aclprofCreateStamp();<br>aclprofSetStampTraceMessage(stamp, "aclmdlExecute_duration", strlen("aclmdlExecute_duration"));<br>aclprofPush(stamp);<br>ret = aclmdlExecute(modelId, input, output);<br>aclprofPop(stamp);<br>aclprofDestroyStamp(stamp);<br>//8.处理模型推理结果<br>//9.释放描述模型输入/输出信息、内存等资源,卸载模型<br>int ret = aclprofGetStepTimestamp(stepInfo, ACL_STEP_END, stream_);<br>aclprofDestroyStepInfo(stepInfo);<br>//10.关闭Profiling配置, 释放配置资源, 释放Profiling组件资源<br>aclprofStop(config);<br>aclprofDestroyConfig(config);<br>aclprofFinalize();<br>//11.释放运行管理资源<br>//12. AscendCL去初始化<br>//......<br> |
|---|
示例三(aclprofRangeStart/aclprofRangeStop示例,适用于单线程或跨线程):
<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> | <br>//1.AscendCL初始化<br>//2.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream<br>ret = aclrtCreateStream(&stream_);<br>//3..Profiling初始化<br>//设置数据落盘路径<br>const char *aclProfPath = "...";<br>aclprofInit(aclProfPath, strlen(aclProfPath));<br>//4.进行Profiling配置<br>uint32_t deviceIdList[1] = {0};<br>//创建配置结构体<br>aclprofConfig *config = aclprofCreateConfig(deviceIdList, 1, ACL_AICORE_ARITHMETIC_UTILIZATION, <br> nullptr,ACL_PROF_ACL_API | ACL_PROF_TASK_TIME);<br>const char *memFreq = "15";<br>ret = aclprofSetConfig(ACL_PROF_SYS_HARDWARE_MEM_FREQ, memFreq, strlen(memFreq));<br>aclprofStart(config);<br>aclprofStepInfo *stepInfo = aclprofCreateStepInfo();<br>int ret = aclprofGetStepTimestamp(stepInfo, ACL_STEP_START, stream_);<br>//5.模型加载,加载成功后,返回标识模型的modelId<br>//6.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output<br>//7.执行模型(模型在跨线程执行)<br>stamp = aclprofCreateStamp();<br>aclprofSetStampTraceMessage(stamp, "aclmdlExecute_duration", strlen("aclmdlExecute_duration"));<br>aclprofRangeStart(stamp, &rangeId);<br>ret = aclmdlExecute(modelId, input, output);<br>aclprofRangeStop(rangeId);<br>aclprofDestroyStamp(stamp);<br>//8.处理模型推理结果<br>//9.释放描述模型输入/输出信息、内存等资源,卸载模型<br>int ret = aclprofGetStepTimestamp(stepInfo, ACL_STEP_END, stream_);<br>aclprofDestroyStepInfo(stepInfo);<br>//10.关闭Profiling配置, 释放配置资源, 释放Profiling组件资源<br>aclprofStop(config);<br>aclprofDestroyConfig(config);<br>aclprofFinalize();<br>//11.释放运行管理资源<br>//12. AscendCL去初始化<br>//......<br> |
|---|
Profiling AscendCL API for Subscription示例代码
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
本节中的示例重点介绍Profiling性能数据采集的代码逻辑,AscendCL初始化和去初始化请参见AscendCL初始化与去初始化,运行管理资源申请与释放请参见运行管理资源申请与释放,模型加载、准备模型推理的输入/输出数据的接口调用流程、模型执行、模型卸载等请参见模型推理。
<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>86<br>87<br>88<br>89<br>90<br>91<br>92<br>93<br>94<br> | <br>// 1.AscendCL初始化<br>// 2.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream<br>// 3.模型加载,加载成功后,返回标识模型的modelId<br>// 4.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output<br>// 5.创建管道(UNIX操作系统下需要引用C++标准库头文件unistd.h),用于读取以及写入模型订阅的数据<br>int subFd[2];<br>// 读管道指针指向subFd[0],写管道指针指向subFd[1] <br>pipe(subFd);<br>// 6.创建模型订阅的配置并且进行模型订阅<br>aclprofSubscribeConfig *config = aclprofCreateSubscribeConfig(1, ACL_AICORE_NONE, &subFd[1]);<br>// 模型订阅需要传入模型的modelId<br>aclprofModelSubscribe(modelId, config);<br>// 7.实现管道读取订阅数据的函数<br>// 7.1 自定义函数,实现从用户内存中读取订阅数据的函数<br>void getModelInfo(void *data, uint32_t len) {<br> uint32_t opNumber = 0;<br> uint32_t dataLen = 0;<br> // 通过AscendCL接口读取算子信息个数<br> aclprofGetOpNum(data, len, &opNumber);<br> // 遍历用户内存的算子信息<br> for (int32_t i = 0; i < opNumber; i++){<br> // 获取算子的模型id<br> uint32_t modelId = aclprofGetModelId(data,len, i);<br> // 获取算子的类型名称长度<br> size_t opTypeLen = 0;<br> aclprofGetOpTypeLen(data, len, i, &opTypeLen);<br> // 获取算子的类型名称<br> char opType[opTypeLen];<br> aclprofGetOpType(data, len, i, opType, opTypeLen);<br> // 获取算子的详细名称长度<br> size_t opNameLen = 0;<br> aclprofGetOpNameLen(data, len, i, &opNameLen);<br> // 获取算子的详细名称<br> char opName[opNameLen];<br> aclprofGetOpName(data, len, i, opName, opNameLen);<br> // 获取算子的执行开始时间<br> uint64_t opStart = aclprofGetOpStart(data, len, i);<br> // 获取算子的执行结束时间<br> uint64_t opEnd = aclprofGetOpEnd(data, len, i);<br> uint64_t opDuration = aclprofGetOpDuration(data, len, i);<br> }<br>}<br>// 7.2 自定义函数,实现从管道中读取数据到用户内存的函数<br>void *profDataRead(void *fd) {<br> // 设置每次从管道中读取的算子信息个数<br> uint64_t N = 10;<br> // 获取单位算子信息的大小(Byte)<br> uint64_t bufferSize = 0;<br> aclprofGetOpDescSize(&bufferSize);<br> // 计算存储算子信息的内存的大小,并且申请内存<br> uint64_t readbufLen = bufferSize * N;<br> char *readbuf = new char[readbufLen];<br> // 从管道中读取数据到申请的内存中,读取到的实际数据大小dataLen可能小于bufferSize * N,如果管道中没有数据,默认会阻塞直到读取到数据为止<br> auto dataLen = read(*(int*)fd, readbuf, readbufLen);<br> // 读取数据到readbuf成功<br> while (dataLen > 0) {<br> // 调用5.1实现的函数解析内存中的数据<br> getModelInfo(readbuf, dataLen);<br> memset(readbuf, 0, bufferSize);<br> dataLen = read(*(int*)fd, readbuf, readbufLen);<br> }<br> delete []readbuf;<br>}<br>// 8. 启动线程读取管道数据并解析<br>pthread_t subTid = 0;<br>pthread_create(&subTid, NULL, profDataRead, &subFd[0]);<br>// 9.执行模型<br>ret = aclmdlExecute(modelId, input, output);<br>// 10.处理模型推理结果<br>// 11.释放描述模型输入/输出信息、内存等资源,卸载模型<br>// 12.取消订阅,释放订阅相关资源<br>aclprofModelUnSubscribe(modelId);<br>pthread_join(subTid, NULL);<br>// 关闭读管道指针<br>close(subFd[0]);<br>// 释放config指针<br>aclprofDestroySubscribeConfig(config);<br>// 13.释放运行管理资源<br>// 14. AscendCL去初始化<br>// ......<br> |
|---|
父主题: 扩展更多特性
溢出算子数据采集及分析
前提条件
使用ATC工具转换模型时,需在转换命令中增加--status_check参数,并将参数值设置为1,表示在编译算子时添加溢出检测逻辑。
关于ATC工具及其参数的详细说明,请参见《ATC工具使用指南》。
采集溢出算子信息
在调用aclInit接口初始化AscendCL时,在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累加出现溢出
-
父主题: 扩展更多特性
共享Buffer管理
本特性提供了跨进程共享Buffer管理能力,可配合共享队列一起使用。共享Buffer的共享范围由共享队列的授权确定,共享范围包括“一主多从”的这些进程。
接口调用流程

关键接口的调用流程如上图所示,流程说明如下:
-
AscendCL初始化。
调用aclInit接口实现初始化AscendCL。
-
运行管理资源申请。
具体流程,请参见运行管理资源申请与释放。
-
申请共享Buffer内存。
调用acltdtAllocBuf接口申请共享Buffer内存,此处需根据实际情况选择内存类型。
-
向共享Buffer中填充有效数据。
需先调用acltdtGetBufData接口获取共享Buffer的数据区指针和数据区长度,接着调用aclrtMemcpy接口把用户数据复制到共享Buffer中,最后可调用acltdtSetBufDataLen接口设置有效数据长度,以便在多进程场景下调用acltdtGetBufDataLen接口获取有效数据长度,再根据有效数据长度获取共享Buffer中的数据。
-
设置共享Buffer的私有数据区数据。
调用acltdtSetBufUserData接口设置共享Buffer的私有数据区数据,以便在多进程场景下调用acltdtGetBufUserData接口获取共享Buffer的私有数据区数据。
-
释放共享Buffer内存。
调用acltdtFreeBuf接口来释放共享Buffer。
-
运行管理资源释放。
接口调用流程,请参见运行管理资源申请与释放。
-
AscendCL去初始化。
调用aclFinalize接口实现AscendCL去初始化。
示例代码
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
<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> | cpp<br>#include "acl/acl.h"<br>// 1. AscendCL初始化<br>// 此处的..表示相对路径,相对可执行文件所在的目录<br>// 例如,编译出来的可执行文件存放在out目录下,此处的..就表示out目录的上一级目录<br>const char *aclConfigPath = "../src/acl.json";<br>aclError ret = aclInit(aclConfigPath);<br>// 2. 运行管理资源申请,指定计算设备,此处以deviceId = 0为例<br>ret = aclrtSetDevice(0);<br>// 3. 申请mbuf内存并进行内存管理,此处以申请DVPP内存、内存大小1024U为例<br>size_t size = 1024U; <br>acltdtBuf buf; <br>ret = acltdtAllocBuf(size, ACL_TDT_DVPP_MEM, &buf);<br>// 4. 向共享Buffer中填充有效数据<br>// 4.1 获取共享Buffer的数据区指针和数据区长度<br>void *dataPtr = nullptr;<br>size_t dataSize = 0U;<br>ret = acltdtGetBufData(buf, &dataPtr, &dataSize);<br>// 4.2 把用户数据拷贝到共享Buffer中<br>size_t len = 512U; // 用户数据长度<br>void *ptr = new (std::nothrow) char_t[len]; // 用户申请自己的内存<br>// 用户对自己申请的数据进行处理<br>//……<br>ret = aclrtMemcpy(dataPtr, size, ptr, len, ACL_MEMCPY_HOST_TO_DEVICE);<br>// 5. 释放内存<br>delete[] ptr;<br>ptr = nullptr;<br>delete[] newPtr;<br>newPtr = nullptr;<br>ret = acltdtFreeBuf(buf);<br>// 6. 运行管理资源释放<br>ret = aclrtResetDevice(0);<br>// 7. AscendCL去初始化<br>ret = aclFinalize();<br> |
|---|
父主题: 扩展更多特性
应用调试
编译及运行应用
-
编译代码。
可参考基于Caffe ResNet-50网络实现图片分类(同步推理)中的说明,主要步骤如下:
-
创建编译脚本。
您可以从该基于Caffe ResNet-50网络实现图片分类(同步推理)样例中获取编译脚本CMakeLists.txt,在该编译脚本的基础上修改如下参数。
-
include_directories:添加头文件所在的目录。依赖的头文件请参见调用接口依赖的头文件和库文件说明。
示例如下:
include_directories(directoryPath1directoryPath2) -
link_directories:添加库文件所在的目录。
示例如下:
link_directories(directoryPath3directoryPath4) -
add_executable:修改可执行文件的名称(例如:main)、添加*.cpp文件所在的目录。
示例如下:
add_executable(maindirectoryPath5directoryPath6) -
target_link_libraries:修改可执行文件的名称(与add_executable中设置的名称保持一致)、添加可执行文件依赖的库文件。依赖的库文件与接口所在的头文件有关,请参见调用接口依赖的头文件和库文件说明。
示例如下:
target_link_libraries(mainascendcllibName1libName2):::note 说明 编译基于AscendCL接口的代码逻辑时,请按照include的头文件依赖对应的库文件,如果引用多余的so文件(例如libascendcl.a),可能导致版本功能异常或后续版本升级时存在兼容性问题。 :::
-
编译选项,修改可执行文件的名称(与与add_executable中设置的名称保持一致),以及可执行文件的安装目录。
示例如下,表示main安装在${CMAKE_INSTALL_PREFIX}/out目录下,${CMAKE_INSTALL_PREFIX}变量定义的路径是相对路径,相对cmake命令执行的路径:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../../../out")install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
-
-
设置环境变量。
如果基于基于Caffe ResNet-50网络实现图片分类(同步推理)样例中的CMakeLists.txt编译脚本进行修改时,则需要设置DDK_PATH、NPU_HOST_LIB环境变量,分别用于指向AscendCL头文件目录、库文件目录。
如下为设置环境变量的示例,${INSTALL_DIR}表示CANN软件安装目录,例如,$HOME/Ascend/ascend-toolkit/latest*,**arch表示操作系统架构,{os}*表示操作系统。
export DDK_PATH=${INSTALL_DIR}export NPU_HOST_LIB=${INSTALL_DIR}/{arch-os}/devlibnote须知
使用“${INSTALL_DIR}/{**arch-os}/devlib”目录下的*.so库,是为了编译基于AscendCL接口的代码逻辑时,不依赖其它组件(例如Driver)的任何*.so库。因此在使用cmake编译命令时,请务必将DCMAKE_SKIP_RPATH设置为TRUE,代表不会将rpath路径(即“${INSTALL_DIR}/{arch-os}/devlib”)添加到编译生成的可执行文件中去。
编译通过后,运行应用时,通过配置环境变量,应用会链接到运行环境上“lib64”目录下的*.so库,运行时会自动链接到依赖其它组件的*.so库。
-
执行cmake命令编译代码。
示例命令如下,其中,“../../../src”表示CMakeLists.txt文件所在的目录,请根据实际目录层级修改;通过-DCMAKE_CXX_COMPILER参数指定的编译器,请根据实际版本要求修改。
-
当开发环境与运行环境操作系统架构相同时,执行如下命令编译:
cmake ../../../src -DCMAKE_CXX_COMPILER=g++ -DCMAKE_SKIP_RPATH=TRUE -
当开发环境与运行环境操作系统架构不同时,执行以下命令进行交叉编译:
例如,当开发环境为X86架构,运行环境为AArch64架构时,执行以下命令进行交叉编译。
cmake ../../../src -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_SKIP_RPATH=TRUE
:::note 说明 关于cmake参数的详细介绍,请参见https://cmake.org/cmake/help/latest/guide/tutorial/index.html,选择对应的版本后再查看参数。 :::
-
-
执行make命令生成可执行文件。
make
-
-
运行可执行文件。
将AscendCL初始化配置文件(acl.json)所在的目录、可执行文件所在的目录、测试图片所在的目录、*.om文件所在的目录都上传到运行环境的同一个目录下,再登录到运行环境,切换到可执行文件所在的目录,运行可执行文件,示例命令如下:
./main如果在AscendCL初始化阶段,在aclInit接口中传入空指针,则无需将AscendCL初始化配置文件(acl.json)所在的目录上传到运行环境。
问题定位
运行应用时如果出错,您可以参见《日志参考》获取日志文件,以便查看日志文件中详细报错。根据报错初步定位后:
- 如果是接口约束导致接口调用逻辑不对,需查看总体的使用约束以及各接口本身的约束,再调整接口调用逻辑。
- 如果是算子在AI Core上运行报错,需要进一步定位算子报错的原因,调用AscendCL提供的接口,获取出错算子的描述信息,用于进一步分析时使用,可参见AI Core异常信息获取,查看原理及调用示例。
DVPP数据处理高性能编程建议
目前在处理图像、视频数据时,可以使用VPC多功能组合接口、VPC批处理接口、合理选择VDEC的输出格式等编码方式,来提升应用的性能,具体编程建议请参见高性能编程建议。
父主题: 精度/性能优化
简介
本文介绍整网推理场景下的精度调优流程、相关配置及典型案例等。由于是调优,因此在调优前,请确保已经完成了整网推理功能调测,功能不阻塞,只是推理精度错误,或推理精度与标杆数据存在少量差距。
在整网推理时,可能由于以下原因导致推理精度错误或者推理精度不达标:
-
推理功能与其它功能之间的串接问题,当前比较典型的是DVPP+AIPP+模型推理串联使用的场景,该场景主要是因为接口中参数的配置问题、模型转换时AIPP的配置问题导致。
如果存在DVPP、AIPP功能、模型推理串联使用的场景,建议先排查这部分问题;否则,可以跳过该排查,直接排查算子本身的精度问题。
-
整网中算子本身的精度问题,该类问题可以借助精度比对工具,根据下文中具体的问题定位流程获取各类数据后,再进行比对、分析,确认是配置问题,还是算子实现问题,再逐一解决问题。本文中会结合具体的比对、分析的案例,介绍如何比对、分析。
图1 推理精度问题

:::note 说明
- 本文中的“推理”,当前限定为使用om离线模型文件进行推理的场景。
- 本文中的算子精度问题,是指整网中算子的精度问题,对于自定义的TBE算子,运行验证时的发现精度问题,请参见《TBE&AI CPU算子开发指南》。 :::
父主题: 模型推理精度提升建议
问题描述
推理结果不达标,包括以下两种情况:
- 算子精度导致推理结果错误,是指整网推理的功能已调通,但推理结果错误,例如目标检测网络MAP结果全0、昇腾om模型的推理结果与标杆网络的推理结果比对时余弦相似度为0。
- 算子精度导致推理精度不达标,是指整网推理的功能已调通,单次昇腾om模型的推理结果与标杆网络的推理结果比对时余弦相似度在95%以上,但数据集推理精度与标杆数据存在少量差距,例如:
- 分类网络昇腾om模型,Top1/Top5分别为:0.90/0.70,;标杆网络Top1/Top5分别为:0.92/0.71。
- 检测网络昇腾om模型MAP精度:0.54;标杆网络MAP精度:0.55。
父主题: 算子精度导致推理结果不达标
在线提单