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

5 算法程序解读

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

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

常用深度学习框架(caffe、TensorFlow等)的算法推理程序主要由三部分组成:

  1. 预处理:准备推理输入数据,如图片颜色通道排列和分离,像素数据转换成浮点数,数据归一化处理等;
  2. 神经网络推理:对输入数据进行推理计算,并输出推理数据,在手写体识别例子中,输出的是预测为0~9这10个数字对应的概率值;
  3. 后处理:对推理输出的数据进行解析,得到最终推理结果,在手写体识别例子中,比较10个数字的概率值,最大概率对应的数字就是推理的结果。

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

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

5.2.1 初始化

  1. 获取模型数据文件大小
  2. 在用户态申请MMZ内存作为模型数据缓存,大小为步骤1的模型文件大小
  3. 将模型数据文件读取(填充)到申请的MMZ内存空间中
  4. 从步骤3加载网络模型数据,并解析出网络模型
  5. 获取网络任务各段辅助内存大小,申请相应缓存空间(申请一块总的内存空间,再切分给任务缓存、输入数据缓存、输出数据缓存使用),设置各个缓存空间内存地址信息
  6. 申请网络推理结果后处理缓存空间,并设置参数
  7. 设置网络预测控制信息,参数数据来源于步骤4解析的网络模型参数数据
  8. 记录(设置)网络推理的辅助内存,即调用HI_MPI_SVP_NNIE_AddTskBuf接口

5.2.2 运行

预处理

  1. 填充输入数
  2. 刷新缓存

推理

  1. 执行网络推理

后处理

  1. 刷新缓存
  2. 读取推理结果,并转换成用户需要的输出信息

5.2.3 销毁

  1. 删除记录(设置)网络推理的辅助内存,即调用HI_MPI_SVP_NNIE_RemoveTskBuf接口
  2. 释放网络任务各段辅助内存
  3. 释放网络推理结果后处理缓存空间
  4. 卸载网络模型,并释放模型数据缓存

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 参考文献

  • <HiSVP 开发指南.pdf>, <HI3516CV500开发资料2019\Hi3516DV300SDK\3516DV300\1\zh\01.software\board\SVP>
  • <HiSVP API 参考.pdf>, <HI3516CV500开发资料2019\Hi3516DV300SDK\3516DV300\1\zh\01.software\board\SVP>
发布于 2019-05-28

文章被以下专栏收录