跳转到主要内容

Vitis AI DPU代码分析

judy 提交于

本文转载自:<span id="profileBt"><a href="https://mp.weixin.qq.com/s/VcdQs88AqPUVb_wTqnb0qA"&gt; 硬码农二毛哥微信公众号</a></span>

<strong>Vitis AI 设计流程</strong>

Vitis AI 和Vitis IDE需要下面三个基本步骤:
<center><img src="http://xilinx.eetrend.com/files/2021-09/%E5%8D%9A%E5%AE%A2/100553321-21…; alt=""></center>

<li>构建模型</li>

<li>构建硬件平台</li>

<li>构建可执行软件</li>

Vitis AI Runtime:使用C++或Python写应用程序

导入Vitis AI Library,运行编译好的模型文件。

<strong>Runtime Overview</strong>

Vitis AI开发套件提供high-leve C++/Python APIs(VART)进行从云到边器件开发。对于边缘DPU,除了VART,还可以使用advanced low-level C++/Python APIs。

<li>VART APIs</li>

VART(Vitis AI Runtime),high-level

<li>Advanced APIs</li>

advanced low-level APIs源于DNNDK(Deep Neural Network Development Kit )

<strong>Programming Model</strong>

理解DPU programming model,需要先明白DPU Kernel,DPU Task,DPU Node和DPU Tensor。

<li>DPU Kernel</li>

通过Vitis AI compiler编译生成的ELF文件就是DPU Kernel,使用dpuLoadKernel() 导入DPU Kernel。

<li>DPU Task</li>

通过dpuCreateTask() 为DPU Kerne创建任务。

<li>DPU Node</li>

DPU Node是网络模型中的基本单元,包含三种类型,boundary input node, boundary output node, and internal node。

boundary input node:the first node in a kernel

boundary output node:the last node in a kernel

internal node:other nodes

通过VAI_C编译后,可获取Input node和output node名字。

<li>DPU Tensor</li>

DPU Tensor是用来存储信息的多维数据集合,Tensor弹性包含height, width, channel等。

通常图片存储格式CHW(ChannelHeightWidth )。

DPU存储输入输出Tensor格式HWC(HeightWidthChannel )。

<strong>VAI_C</strong>

Once the compilaton is successful, VAI_C will generate ELF object fles and kernel informaton for deployment

运行docker

<pre>./docker_un.sh xilinx/vitis-ai:1.2.82</pre>

activate TensorFlow tool conda environment
<pre>conda activate vitis-ai-tensorflow</pre>

运行dlet,从HWH中解析DPU配置参数
<pre>$ dlet -f ./system.hwh
[DLet]Generate DPU DCF file dpu-06-18-2020-12-00.dcf successfully.</pre>

打开arch.json,确保dcf参数与生成DCF文件名一致
<center><img src="http://xilinx.eetrend.com/files/2021-09/%E5%8D%9A%E5%AE%A2/100553321-21…; alt=""></center>

下载resnet-50
<pre>./download_model.sh</pre>

tf_resnetv1_50_imagenet_224_224_6.97G:

tf:Tensorflow

resnetv1_50:神经网络

imagenet:数据集

224_224:输入数据大小

6.97G:处理器计算能力

使用VAI_C编译网络模型
<pre>./custom_platform_compile.sh</pre>

DPU Nodes name
<img src="http://xilinx.eetrend.com/files/2021-09/%E5%8D%9A%E5%AE%A2/100553321-21…; alt="">

将生成的.elf文件拷贝到vitis工程中

deactivate TensorFlow tool conda environment

<pre>conda deactivate</pre>

退出docker
<pre>exit</pre>

<strong>Advanced APIs开发步骤</strong>

1. dpuOpen() 打开DPU

2. kernelResnet50 = dpuLoadKernel(KRENEL_RESNET50) 导入DPU kernel Resnet50

3. taskResnet50 = dpuCreateTask(kernelResnet50, 0) 创建任务

4. runResnet50(taskResnet50) 运行任务

5. dpuDestroyTask(taskResnet50) 销毁任务

6. dpuDestroyKernel(kernelResnet50) 销毁DPU kernel,释放资源

7. dpuClose() 关闭DPU

第4步runResnet50为自定义函数,函数中调用API dpuRunTask() 运行DPU任务。

<strong>runResnet50</strong>

ListImages()
<center><img src="http://xilinx.eetrend.com/files/2021-09/%E5%8D%9A%E5%AE%A2/100553321-21…; alt=""></center>

该函数输入为待预测图片路径path,将path路径内图片文件名存储到vector输出。

<li>判断path是否是有效的目录</li>

<li>打开目录</li>

<li>读取每一条目录</li>

<li>判断文件类型是否为图片</li>

<li>将图片名存入vector</li>

<li>关闭目录</li>

<li>对图片进行排序</li>

LoadWords()
<img src="http://xilinx.eetrend.com/files/2021-09/%E5%8D%9A%E5%AE%A2/100553321-21…; alt="">

<li>打开指定路径文件words.txt</li>

<li>读取文档中每行数据,将数据写入vector</li>

dpuGetOutputTensorAddress():获取输出Tensor地址

dpuGetOutputTensorSize():获取输出Tensor size(Byte)

dpuGetOutputTensorChannel():获取输出Tensor channel,分类的种类

dpuGetOutputTensorScale():获取输出Tensor scale value

dpuSetInputImage2():将图片送到DPU,caffe 模块使用

dpuRunTask():运行DPU任务

dpuGetTaskProfile():获取DPU任务执行时间

dpuRunSoftmax():输入包括进入softmax数据地址、分类种类、scale,输出分类结果。

TopK():
<center><img src="http://xilinx.eetrend.com/files/2021-09/%E5%8D%9A%E5%AE%A2/100553321-21…; alt=""></center>
输入d为softmax的结果,输出顺序与标签顺序一致。size为分类的种类,k指定输出分类结果个数,vkinds为标签数据。该函数显示概率最高的前k个预测结果。