爱笑的小姐姐 · 2021年11月18日

【Tengine部署】NPU初体验 踩坑最全总结

1. VIM3安装Ubuntu系统

  • 在Khadas官网下载VIM3 Ubuntu固件,我选择安装 Linux4.9内核固件 桌面版 EMMC安装,文件大约780MB 网址
  • 解压固件压缩包,可以看到解压后的文件后缀名是.img,解压后的文件大概4.5GB
  • 通过USB-C线安装系统到eMMC 链接,下载安装工具USB_Burning_Tool_v2.x.x.exe
  • 此时的状态是板子只用type-c的线连接电脑,用电脑供电,板子此时不连接HDMI显示器,否则会供电失败
  • 运行工具,点击File->Import image选择要升级的固件

image.png

  • 先按住电源键,再短按一下复位键,约4~5秒后开发板就进入烧写模式,此时松开电源键。烧写工具显示已连接开发板

image.png

  • 点击开始按钮开始烧录,等待一段时间,大约12分钟

image.png

  • 烧录结束后,点击停止,关闭工具,断开与电脑连接,连接外部供电,连接HDMI显示器

2. Win10远程连接VIM3

  • 板子上打开terminal,输入ifconfig,查看inet地址
  • 在PC上使用mobaxterm工具进行ssh连接,PC和板子连在同一wifi下,配置板子的ip地址,用户名以及端口

image.png

  • 输入密码,连接成功
  • 此时可以在PC上传输文件到板子上了,当然也可以拔掉显示器了

3. 拉取代码

这里假设是直接从 github 拉取代码,并且是拉取到同一个文件夹里。

拉取 TIM-VX

$ git clone https://github.com/VeriSilicon/TIM-VX.git

拉取 Tengine-Lite

$ git clone https://github.com/OAID/Tengine.git tengine-lite
$ cd tengine-lite

VIM3/VIM3L 的 linux 平台是有 NPU 预置驱动的,可以通过 sudo apt list --installed 查看已经安装的版本:

khadas@Khadas:~$ sudo apt list --installed | grep aml-npu
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
aml-npu/now 6.4.3CB-2 arm64
khadas@Khadas:~$ 

准备代码

$ cd <tengine-lite-root-dir>
$ cp -rf ../TIM-VX/include  ./source/device/tim-vx/
$ cp -rf ../TIM-VX/src      ./source/device/tim-vx/

准备 VIM3/VIM3L 最新版本 3rdparty 依赖

最佳实践是升级系统到最新版本,使得 NPU 的版本 >= 6.4.4。此时没有预置的 3rdparty,所以优先推荐的是采用在板上编译的方式进行编译,这时由于必要的 TIM-VX 依赖用户态驱动的 so 都已在系统目录下,不用准备 3rdparty 下的 lib 目录。参考命令如下:

wget -c https://github.com/VeriSilicon/TIM-VX/releases/download/v1.1.28/aarch64_S905D3_D312513_A294074_R311680_T312233_O312045.tgz
tar zxvf aarch64_S905D3_D312513_A294074_R311680_T312233_O312045.tgz
mv aarch64_S905D3_D312513_A294074_R311680_T312233_O312045 prebuild-sdk-s905d3
cd <tengine-lite-root-dir>
mkdir -p ./3rdparty/tim-vx/include
mkdir -p ./3rdparty/tim-vx/lib/aarch64
cp -rf ../prebuild-sdk-s905d3/include/*  ./3rdparty/tim-vx/include/

准备 VIM3/VIM3L 最新版本的编译

在板子上进行本地编译很简单,参考命令如下:

cd <tengine-lite-root-dir>
mkdir build && cd build
cmake -DTENGINE_ENABLE_TIM_VX=ON ..
make -j`nproc` && make install

4. 编译模型转换工具

工具链接

只能在linux上运行

sudo apt install libprotobuf-dev protobuf-compiler

这部可能会报错,因为ubuntu默认安装protobuf是2.6,而要求的版本是至少3.6.1

出错解决方案参考链接

# 安装依赖
sudo apt-get install autoconf automake libtool curl make g++ unzip

wget https://github.com/protocolbuffers/protobuf/releases/download/v3.19.1/protobuf-all-3.19.1.tar.gz
tar -zxvf protobuf-all-3.19.1.tar.gz
cd protobuf-3.19.1

# configure
./configure --prefix=/usr

# make
make -j16
make check   # 非必须
sudo make install 
sudo ldconfig  # refresh

protoc --version  # 查看版本

安装好后,继续来编译tengine的convert tools

cd tengine-lite
mkdir build && cd build
cmake -DTENGINE_BUILD_CONVERT_TOOL=ON..
make -j`nproc` && make install

编译完成后,生成的可执行文件 convert_tool 存放在 ./build/install/bin/ 目录下。

cd ./build/install/bin
./convert_tool -h  # 通过help指令查看convert的参数有哪些

onnx模型转换成tmfile

./convert_tool -f onnx -m mobilenet.onnx -o mobilenet.tmfile

5. 编译量化工具

注意:量化工具只能在x86的机器上编译,我这里展示ubuntu的编译方法,win10上没成功(因为我的opencv是预编译的,使用cmake编译的opencv应该可以成功)

  • 安装/升级cmake
wget https://cmake.org/files/v3.20/cmake-3.20.2-linux-x86_64.tar.gz
tar -xzvf cmake-3.20.2-linux-x86_64.tar.gz

# 解压出来的包,将其放在 /opt 目录下,其他目录也可以,主要别以后不小心删了
sudo mv cmake-3.20.2 /opt/cmake-3.20.2

# 查看使用的cmake目录(升级版本使用)  我这里显示的是/usr/local/bin/cmake
which cmake

# 建立软链接
sudo ln -sf /opt/cmake-3.20.1/bin/* /usr/local/bin/

# 查看 cmake 版本
cmake --version
  • 编译tengine-lite
sudo apt-get update
sudo apt install libopencv-dev

git clone https://github.com/OAID/Tengine.git  tengine-lite
cd tengine-lite
mkdir build 
cd build
cmake -DTENGINE_BUILD_QUANT_TOOL=ON ..
make && make install

量化工具的路径在 ./install/bin/目录下

$ tree install/bin/
install/bin/
├── quant_tool_int8
├── quant_tool_uint8
├── ......

执行quant_tool的help,查看参数说明,还会给出一个示例

image.png

图中的quant_dataset/imagenet是一个校准数据集的目录,存一堆图片的,官方推荐500~1000张,我这里提供一下我使用的imagenet抽取的脚本和数据集,方便大家使用和修改

import os
import random
import shutil

# imagenet验证集目录
src = '/data/datasets/Imagenet2012/val/'
# 抽取的文件存放的目录
dst = '/data/quant-imagenet/'
# 每个类别抽取一张图片,复制到dst下
for cls in os.listdir(src):
    cls_root = os.path.join(src, cls)
    files = os.listdir(cls_root)
    files = random.sample(files, 1)
    for file in files:
        shutil.copyfile(os.path.join(cls_root, file), os.path.join(dst, file))

校准数据集放在百度云上了,链接:校准数据集 提取码:ipw6

量化完成后,我这边是选择下载回windowsPC上,这里随意,看自己在什么系统的PC上开发方便,然后执行编译好的uint8可执行文件。

6. 测试效果

下图是在PC上的测试,左边是fp32的执行结果,右边是uint8的执行结果,从结果来看量化效果是成功了的,从执行时间上实际效果变差了。原因应该是在执行网络的之前要进行量化,网络推理后要对结果进行反量化操作,大概是反量化这里没有做好优化。
image.png

下面进行VIM3板卡的效果对比
image.png

可以看出,开启NPU的速度效果很显著,就是精度稍差了一些,不过imagenet数据集类别太多,量化校准的时候每个类只sample了一张图片,猜测是校准数据集太小了。

原文链接:https://zhuanlan.zhihu.com/p/431376048
作者:闪电侠的右手

推荐阅读

更多Tengine相关内容请关注Tengine-边缘AI推理框架专栏。
推荐阅读
关注数
3393
内容数
68
Tengine是一款轻量级模块化高性能的神经网络推理引擎 ;欢迎体验Tengine,[链接] 《Tengine开发者入门资料包》[链接]
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息