gpu开发 海思_海思AI芯片开发上手笔记 - 算法程序解读

5 算法程序解读

前面章节已经成功运行sample程序,迫不及待地想知道程序怎么写,好不好掌握。本文以手写体图片数字识别为例,介绍海思芯片上AI算法推理程序的框架、数据结构、API调用、运行流程等内容。

5.1 常用深度学习框架推理步骤

常用深度学习框架(caffe、TensorFlow等)的算法推理程序主要由三部分组成:预处理:准备推理输入数据,如图片颜色通道排列和分离,像素数据转换成浮点数,数据归一化处理等;

神经网络推理:对输入数据进行推理计算,并输出推理数据,在手写体识别例子中,输出的是预测为0~9这10个数字对应的概率值;

后处理:对推理输出的数据进行解析,得到最终推理结果,在手写体识别例子中,比较10个数字的概率值,最大概率对应的数字就是推理的结果。

对于异构计算平台,如GPU、TPU等,在预处理、后处理以及推理过程中部分网络层需要CPU参与计算的,就会涉及到异构计算单元之间的交互,如数据传输,过程同步等。这种交互由深度学习框架内部进行封装处理,开发者只要遵守框架的接口和过程等约定,就能成功进行推理计算。

5.2 海思芯片AI算法推理过程

5.2.1 初始化获取模型数据文件大小

在用户态申请MMZ内存作为模型数据缓存,大小为步骤1的模型文件大小

将模型数据文件读取(填充)到申请的MMZ内存空间中

从步骤3加载网络模型数据,并解析出网络模型

获取网络任务各段辅助内存大小,申请相应缓存空间(申请一块总的内存空间,再切分给任务缓存、输入数据缓存、输出数据缓存使用),设置各个缓存空间内存地址信息

申请网络推理结果后处理缓存空间,并设置参数

设置网络预测控制信息,参数数据来源于步骤4解析的网络模型参数数据

记录(设置)网络推理的辅助内存,即调用HI_MPI_SVP_NNIE_AddTskBuf接口

5.2.2 运行

预处理填充输入数

刷新缓存

推理执行网络推理

后处理刷新缓存

读取推理结果,并转换成用户需要的输出信息

5.2.3 销毁删除记录(设置)网络推理的辅助内存,即调用HI_MPI_SVP_NNIE_RemoveTskBuf接口

释放网络任务各段辅助内存

释放网络推理结果后处理缓存空间

卸载网络模型,并释放模型数据缓存

5.3 主要API说明

NNIE 模块提供了创建任务和查询任务的基本接口。 用户根据需求调用相应的算子接口创建任务,指定是否阻塞等待结果,即 bInstant 类型,并记录该任务返回的 handle 号。根据返回的 handle 号,指定阻塞方式,可以查询到该任务的完成状态。HI_MPI_SVP_NNIE_LoadModel:从用户事先加载到 buf 中的模型中解析出网络模型。

HI_MPI_SVP_NNIE_GetTskBufSize:获取给定网络任务各段辅助内存大小。

HI_MPI_SVP_NNIE_Forward:多节点输入输出的 CNN 类型网络预测。

HI_MPI_SVP_NNIE_ForwardWithBbox:多个节点 feature map 输入。

HI_MPI_SVP_NNIE_UnloadModel:卸载模型。

HI_MPI_SVP_NNIE_Query:查询任务是否完成。

HI_MPI_SVP_NNIE_AddTskBuf:记录 TskBuf 地址信息。

HI_MPI_SVP_NNIE_RemoveTskBuf:移除 TskBuf 地址信息。

5.4 参考程序解读

在海思SDK的package/mpp_smp_linux/sample/svp/nnie路径下可以找到参考程序代码。

很多人在阅读海思sample程序时,被各种结构体定义及关系给弄糊涂了。本来刚入门,面对海思官方文档标准API已经很陌生了,SAMPLE程序对API和结构体又进行了再次封装,且所有NNIE例子都写在同一个代码文件中(4000多行,一看就头大),增加读者阅读和理解代码的难度。

参考程序目录结构说明如下:

mpp_smp_linux

├── include SDK头文件

├── lib SDK动态库和静态库文件

└── sample

├── common sample公共程序和头文件

└── svp SVP模块参考程序

├── common SVP模块公共程序和头文件

└── nnie NNIE模块参考程序

├── sample_nnie_main.c NNIE参考程序main入口

├── sample_nnie_software 网络推理CPU执行部分,包括后处理

├── sample NNIE参考程序实现代码

└── data 测试数据目录

├── nnie_image 测试图片

└── nnie_model 测试模型

算法代码逻辑从main函数的case分支进入各个网络类型的处理函数,手写体识别对应SAMPLE_SVP_NNIE_Cnn函数,流程已在5.2小节中详细说明,这里讲解几个NNIE sample的公共数据结构。

模型管理结构:

typedef struct hiSAMPLE_SVP_NNIE_MODEL_S {

SVP_NNIE_MODEL_S stModel; // 解析后的模型结构,调用HI_MPI_SVP_NNIE_LoadModel解析的结果

SVP_MEM_INFO_S stModelBuf; // 模型文件的数据缓存,由用户填充

} SAMPLE_SVP_NNIE_MODEL_S;

引擎执行参数:

typedef struct hiSAMPLE_SVP_NNIE_PARAM_S {

// 模型结构参数

SVP_NNIE_MODEL_S* pstModel;

// 网络推理辅助内存tmpBuf大小,来源于pstModel的u32TmpBufSize字段

HI_U32 u32TmpBufSize;

// 网络任务各段辅助内存大小,由HI_MPI_SVP_NNIE_GetTskBufSize接口获取

HI_U32 au32TaskBufSize[SVP_NNIE_MAX_NET_SEG_NUM];

// 网络任务辅助内存起始信息

SVP_MEM_INFO_S stTaskBuf;

// 网络推理辅助内存tmpBuf起始信息

SVP_MEM_INFO_S stTmpBuf;

// store Lstm step info

SVP_MEM_INFO_S stStepBuf;

// 网络输入/输出的数据(blob)参数信息

SAMPLE_SVP_NNIE_SEG_DATA_S astSegData[SVP_NNIE_MAX_NET_SEG_NUM];

// CNN/DNN/RNN网络预测控制参数,参数数据来源于加载模型文件解析后的网络模型参数

SVP_NNIE_FORWARD_CTRL_S astForwardCtrl[SVP_NNIE_MAX_NET_SEG_NUM];

// 有 Bbox 输入的目标检测网络预测控制参数,参数数据来源于加载模型文件解析后的网络模型参数

SVP_NNIE_FORWARD_WITHBBOX_CTRL_S astForwardWithBboxCtrl[SVP_NNIE_MAX_NET_SEG_NUM];

} SAMPLE_SVP_NNIE_PARAM_S;

网络执行CPU部分(后处理)

typedef struct hiSAMPLE_SVP_NNIE_CNN_SOFTWARE_PARAM_S {

HI_U32 u32TopN; // 获取类别概率值最高的前N个

SVP_DST_BLOB_S stGetTopN; // 前N个类别输出的内存信息

SVP_MEM_INFO_S stAssistBuf; // 辅助内存信息

} SAMPLE_SVP_NNIE_CNN_SOFTWARE_PARAM_S;

5.5 注意事项硬件为了快速访问内存首地址或者跨行访问数据,在使用 DDR4 时,为提高访存效率,建议首地址使用 256 字节对齐,stride 使用 256 字节的奇数倍对齐。

典型的 RGB\HSV\LAB 图像 Planar 格式存储,NNIE 默认以 B\G\R、H\S\V、L\A\B 顺序按通道平面进行存储。

5.6 参考文献,

,

你可能感兴趣的:(gpu开发,海思)