【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选择要升级的固件

放个开发板购买链接

Khadas VIM3 5TOPs NPU开发板
淘宝
¥750.00
去购买
先按住电源键,再短按一下复位键,约4~5秒后开发板就进入烧写模式,此时松开电源键。烧写工具显示已连接开发板点击开始按钮开始烧录,等待一段时间,大约12分钟烧录结束后,点击停止,关闭工具,断开与电脑连接,连接外部供电,连接HDMI显示器
Khadas VIM3开发板固件烧写记录blog.csdn.net/Lozenyi/article/details/117780349?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-4.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-4.essearch_pc_relevant

2. Win10远程连接VIM3

板子上打开terminal,输入ifconfig,查看inet地址

在PC上使用mobaxterm工具进行ssh连接,PC和板子连在同一wifi下,配置板子的ip地址,用户名以及端口

输入密码,连接成功

此时可以在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

出错解决方案参考链接

protobuf/README.md at master · protocolbuffers/protobuf (github.com)github.com/protocolbuffers/protobuf/blob/master/src/README.md
# 安装依赖 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,查看参数说明,还会给出一个示例

图中的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的执行结果,从结果来看量化效果是成功了的,从执行时间上实际效果变差了。原因应该是在执行网络的之前要进行量化,网络推理后要对结果进行反量化操作,大概是反量化这里没有做好优化。

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

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