DDK 与 NPU 版本确认
Amlogic 的 DDK 与 SDK 是分开的,DDK 的获取需要单独找供应商获取,需要注意的是使用的 DDK 版本要和 npu 驱动版本一致,版本不一致会导致在运行的时候出现段错误或其他未知错误。开发板使用的是荣品的A311D开发板,镜像为荣品提供的 ubuntu20.04 系统镜像,默认安装了 NPU 的运行环境。
驱动版本可以在开发板终端使用指令查看
$ dmesg | grep Galcore
[ 8.975803] Galcore version 6.4.3.279124CB # 版本信息
将 DDK 压缩包解压后目录结构如下,不同版本的 DDK 目录结构有所不同,以实际目录结构为准
DDK_XXX_SDK V0.1.zip 版本是基于模型转换出的 case demo 整理的一个 sdk 开发包。提供一个基于 case demo 去编译、集成的开发环境。
DDK_XXX_SDK_VXXX.zip版本是 Amlogic 基于 case demo 提取并封装的一套接口,用以屏蔽 DDK 版本升级时转出的 case demo 中一些接口的变动。因为当前有些流程涉及到使用 sdkv0.1 开发包,需自行选择使用哪套 sdk 进行集成开发。
6.4.3 版本
linux 系统
DDK_6.4.3_SDK V0.1.zip 文件名包含有空格,在解压之前最好重命名,去掉空格或者替换空格为 "__",解压后会产生两个压缩包,一个是 android_sdk_643.rar,另一个是 linux_sdk_643.rar ,这里是linux平台,所以继续解压 linux_sdk_643.rar 压缩包,如果是安卓平台则解压 android_sdk_643.rar,并参考[[ 安卓系统 ]](# Android 系统)
$ unrar x linux_sdk_643.rar && # 解压后会生成 buildroot_sdk_643 目录
$ cd buildroot_sdk_643
|-- buildroot_sdk #sdk 用于编译 demo 程序
`-- conversion_scripts_nbg_unify #demo 模型加 case 源码
然后进入 conversion_scripts_nbg_unify 目录
$ cd conversion_scripts_nbg_unify
修改编译脚本
编译之前需要修改编译脚本 build_vx.sh ,主要修改一下内容
- 修改 AQROOT 变量
export AQROOT=/home/test/a311d-linux/SDK/DDK6.4.3/buildroot_sdk_643/buildroot_sdk
AQROOT 变量需要配置为 buildroot_sdk 的绝对路径。
- 增加交叉编译工具的环境变量
#added by rppdzkj
export TOOLCHAIN=/home/test/a311d-linux/toolchain/gcc/linux-x86/aarch64/gcc-linaro-aarch64-linux-gnu-4.9/bin
export LIB_DIR=/home/test/a311d/a311d-linux/toolchain/gcc/linux-x86/aarch64/gcc-linaro-aarch64-linux-gnu-4.9/arm-linux-gnueabihf/libc/lib
export PATH=/home/test/a311d-linux/toolchain/gcc/linux-x86/aarch64/gcc-linaro-aarch64-linux-gnu-4.9/bin:$PATH
export OPENCV_ROOT=/home/test/a311d-linux/output/mesong12b_w400_release/build/opencv3-3.4.3
export KERNEL_DIR=/home/test/a311d-linux/output/mesong12b_w400_release/build/linux-amlogic-4.9-dev
TOOLCHAIN:A311D SDK 的交叉编译工具的绝对路径
LIB_DIR:A311D SDK 的交叉编译工具的连接库的绝对路径
PATH:当前系统的 PATH 变量
OPENCV_ROOT:A311D SDK 编译过的 OpenCV 绝对路径
KERNEL_DIR:A311D SDK 编译过的 kernel 绝对路径
说明:文档中的配置只是举例,具体修改要根据当前主机的实际路径进行配置。
编译
修改完成后先删除 bin_r 目录
$ rm -rf ./bin_r/
然后赋予脚本可执行权限
$ chmod +x build_vx.sh
最后编译
$ ./build_vx.sh arm64
...
make: Nothing to be done for 'all'. # 编译完成标志
如果编译成功,则会重新生成 bin_r 目录。
$ ls ./bin_r/
main.o mobilenettf vnn_mobilenettf.o vnn_post_process.o vnn_pre_process.o
运行
运行除了将编译产生的可执行文件、模型和图片复制到开发板上以外,还需要 buildroot_sdk 下的链接库文件
$ tree ../buildroot_sdk/build/sdk/drivers_64/
|-- galcore.ko
|-- libArchModelSw.so
|-- libCLC.so
|-- libGAL.so
|-- libNNArchPerf.so
|-- libOpenCL.so
|-- libOpenCL.so.1
|-- libOpenCL.so.1.2
|-- libOpenVX.so
|-- libOpenVX.so.1
|-- libOpenVX.so.1.2
|-- libOpenVXU.so
|-- libVSC.so
|-- libVivanteOpenCL.so
`-- libovxlib.so
以上库文件除了 galcore.ko 以外,都需要复制到开发板的 /lib/ 目录下,然后将 mobilenettf、network_binary_88.nb 和 space_shuttle_224.jpg 这三个文件复制到开发板的合适的位置,这里以 /npu_test/ 为例
$ ls /npu_test/
mobilenettf network_binary_88.nb space_shuttle_224.jpg
然后运行,在运行之前一定要将库文件放到 /lib/ 目录下
$ cd /npu_test/
$ ./mobilenettf network_binary_88.nb space_shuttle_224.jpg
如果一切顺利,就可以看到模型推理信息
Android 系统
对于安卓系统,则需要在解压的时候解压 android_sdk_643.rar 压缩包
$ unrar x android_sdk_643.rar && # 解压后会生成 android_sdk_643 目录
$ cd android_sdk_643
然后参考目录下的 ReadMe.txt 文档操作即可
6.4.6 版本
荣品最新的镜像已经更新到了6.4.6版本,原始包是一个zip的压缩文件包DDK_6.4.6.2.zip,这个包最好不要再linux系统下解压,在windows上解压后会看到文件名包含了很多空格,可以手动把空格删掉,再把文件拷贝到linux平台上。
linux 系统
以下操作均在A311D开发板的 ubuntu20.04 系统上操作
DDK_6.4.6.2_SDK_V1.8.2
使用 DDK_6.4.6.2_SDK_V1.8.2 的SDK 可以参考如下步骤编译
1.解压SDK
解压之前最好先重命名SDK删掉名字中包含的空格
$ tar -xvzf DDK_6.4.6.2_sdk_DDK_6.4.6.2_SDK_V1.8.2.tar.gz
解压后生成 DDK_6.4.6.2_SDK_V1.8.2 目录
$ ls -l
drwxrwxr-x 3 test test 4096 Oct 22 19:45 DDK_6.4.6.2_SDK_V1.8.2
$ cd DDK_6.4.6.2_SDK_V1.8.2/
$ ls -l
drwxrwxr-x 4 test test 4096 Jun 28 11:01 linux_nnsdk_v1.8.2
-rw-rw-r-- 1 test test 5353 Jun 29 19:28 release_note.txt
$ cd linux_nnsdk_v1.8.2
$ ls -l
drwxrwxr-x 6 test test 4096 Oct 23 11:43 demo
drwxrwxr-x 4 test test 4096 Jun 28 11:10 linux_nn_sdk_V1.8
-rw-rw-r-- 1 test test 2812 Jun 28 12:06 readme.txt
$ cd demo
$ ls -l
-rw-rw-r-- 1 test test 1392 Oct 22 19:59 CMakeLists.txt
drwxrwxr-x 2 test test 4096 Jun 28 11:01 include
-rw-rw-r-- 1 test test 14089 Jun 28 11:31 main.cpp
-rw-rw-r-- 1 test test 1815 Mar 25 2021 nn_demo.h
drwxrwxr-x 5 test test 4096 Jun 28 11:01 opencv
-rw-rw-r-- 1 test test 519222 Oct 22 20:16 out_obj_det.bmp
drwxrwxr-x 2 test test 4096 Jun 28 11:22 package
-rw-rw-r-- 1 test test 15359 Mar 25 2021 postprocess_util.c
-rw-rw-r-- 1 test test 132744 Jun 28 11:38 sdk182_32
-rwxrwxr-x 1 test test 171024 Jun 28 11:38 sdk182_64
2.修改cmake配置文件
修改CMakeList.txt 文件
#SET(ARM_32 arm_32)
SET(ARM_64 arm_64) #编译arm64
#SET(GCC_PATH /home/dengliu/work/05_compile_too)
直接在开发板上编译无需指定交叉编译工具
#注释掉交叉编译工具的指定
if(DEFINED ARM_64)
# SET(COMPILER ${GCC_PATH}/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin)
# SET(CMAKE_C_COMPILER ${COMPILER}/aarch64-linux-gnu-gcc)
# SET(CMAKE_CXX_COMPILER ${COMPILER}/aarch64-linux-gnu-g++)
SET(LINK_DIR ../linux_nn_sdk_V1.8/lib/lib64 ${OPENCV_ROOT}/lib64 ./)
elseif(DEFINED ARM_32)
# SET(COMPILER ${GCC_PATH}/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin)
# SET(CMAKE_C_COMPILER ${COMPILER}/arm-linux-gnueabihf-gcc)
# SET(CMAKE_CXX_COMPILER ${COMPILER}/arm-linux-gnueabihf-g++)
SET(LINK_DIR ../linux_nn_sdk_V1.8/lib/lib32 ${OPENCV_ROOT}/lib32 ./)
endif()
3.编译
创建一个build 文件夹并且进入
$ mkdir build && cd build
开始编译
$ cmake ..
$ make
编译完成后会生成一个 sdk180_64 的可执行文件
$ ls -l
-rw-rw-r-- 1 test test 13883 Oct 22 19:59 CMakeCache.txt
drwxrwxr-x 5 test test 4096 Oct 23 12:11 CMakeFiles
-rw-rw-r-- 1 test test 1569 Oct 22 19:59 cmake_install.cmake
-rw-rw-r-- 1 test test 5813 Oct 22 19:59 Makefile
-rwxrwxr-x 1 test test 171000 Oct 23 12:11 sdk180_64
4.运行
$ ./sdk180_64 ../package/object_detect_88.nb 99 ../package/416x416x3.jpg
nettype is 99
the input type should be 416*416*3
object_num:1
class:aeroplane,prob:0.664249
$ ./sdk180_64 ../package/image_classify_88.nb 0 ../package/224x224x3.jpeg
nettype is 0
the input type should be 224*224*3
2: 16.344051
116: 12.786162
843: 9.673010
444: 9.561826
795: 9.117090
运行需要注意的是 A311D上只能使用后缀为 "_88" 的模型,其他模型是其他芯片上使用的,不适用于A311D
DDK_6.4.6.2_SDK_V0.1
解压DDK_6.4.6.2_sdk_DDK_6.4.6.2_SDK_V0.1.tar.gz 后进入 DDK_6.4.6.2_SDK_V0.1/buildroot_sdk_6462/demo_nbg_unify/ 目录修改编译脚本
$ vi build_vx.sh
...
export AQROOT=`realpath ../buildroot_sdk` # 需要指定buildroot_sdk目录的绝对路径
export SDK_DIR=$AQROOT/build/sdk
...
arm-amlogic)
echo $BUILD_OPTIONS_COMPILER_NBG_CASE
if [ $1 = "arm64" ]; then
export ARCH_TYPE=arm64
export CPU_TYPE=cortex-a53
export CPU_ARCH=armv8-a
export FIXED_ARCH_TYPE=arm64
export CROSS_COMPILE= # 开发板上无需指定编译工具,直接配置为空就好
export VIVANTE_SDK_LIB=$SDK_DIR/../so/drivers_64
cp $VIVANTE_SDK_LIB/libovxlib.so $OVXLIB_DIR/lib/libovxlib.so
cp $VIVANTE_SDK_LIB/libjpeg.a $OVXLIB_DIR/lib/libjpeg.a
else
export ARCH_TYPE=arm
export CPU_TYPE=cortex-a9
export CPU_ARCH=armv7-a
export FIXED_ARCH_TYPE=arm-gnueabihf
#export CROSS_COMPILE=arm-linux-gnueabihf-
export VIVANTE_SDK_LIB=$SDK_DIR/../so/drivers_32
cp $VIVANTE_SDK_LIB/libovxlib.so $OVXLIB_DIR/lib/libovxlib.so
cp $VIVANTE_SDK_LIB/libjpeg.a $OVXLIB_DIR/lib/libjpeg.a
fi
;;
...
然后开始编译
$ rm bin_r*
$ ./build_vx.sh arm64
...
make: Nothing to be done for 'all'. # 编译完成标志
编译完成后会生成 bin_r 目录
ls bin_r/ -l
-rw-rw-r-- 1 test test 7440 Oct 23 13:39 main.o
-rwxrwxr-x 1 test test 133152 Oct 23 13:39 mobilenettf
-rw-rw-r-- 1 test test 5352 Oct 23 13:39 vnn_mobilenettf.o
-rw-rw-r-- 1 test test 4488 Oct 23 13:39 vnn_post_process.o
-rw-rw-r-- 1 test test 21416 Oct 23 13:39 vnn_pre_process.o
运行
$ ./bin_r/mobilenettf network_binary_88.nb attach_input_out0_1_out0_1_224_224_3.tensor
Create Neural Network: 17ms or 17066us
Verify...
Verify Graph: 1ms or 1007us
Start run graph [1] times...
Run the 1 time: 6.00ms or 6218.00us
vxProcessGraph execution time:
Total 6.00ms or 6256.00us
Average 6.26ms or 6256.00us
--- Top5 ---
813: 0.999023
405: 0.000266
868: 0.000135
896: 0.000108
0: 0.000000
模型转换
A311D的模型转换需要搭建 python3.5 的环境,推荐使用 ubuntu16.04 操作系统的主机或者虚拟机搭建环境,当前工具支持转换的模型有 tensorflow、caffe、tflite、darknet、onnx、pytorch,keras 类型的模型。如果开发者是其他类型的模型,需先将模型转换成上述支持的一种。
环境搭建
安装 python3 以及 pip 等工具
$ sudo apt-get install python3 python3-pip python3-virtualenv
安装相关依赖包
获取 acuity-toolkit 工具包,进入根目录。
$ for req in $(cat requirements.txt); do pip3 install $req -i \ https://pypi.tuna.tsinghua.edu.cn/simple; done
这一步的安装可能会报很多错误,比如找不到tensflow的2.3版本等,可以参考如下指令升级 pip3 后再做尝试
$ curl https://bootstrap.pypa.io/pip/3.5/get-pip.py -o get-pip.py
$ sudo python3 get-pip.py
安装完成后检查环境
$ python3 bin/checkenv.py
Env Info: Linux distribution is Ubuntu 16.04, please make sure python 3.5 installed.
Env Pass: Require machine type 64bit installed
Env Pass: Require OS type 64bit installed
Env Pass: All Processors support instruction set avx
Env Pass: Python 3.5.2 installed, require 3.5.x
2021-10-26 11:49:21.030538: W tensorflow/stream_executor/platform/default/dso_loader.cc:59] Could not load dynamic library 'libcudart.so.10.1'; dlerror: libcudart.so.10.1: cannot open shared object file: No such file or directory
2021-10-26 11:49:21.030581: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
Env Pass: Require python lib tensorflow version >= 2.3.0 installed.
Env Pass: Require python lib numpy version >= 1.18.0 installed.
Env Pass: Require python lib google.protobuf version >= 3.11.2 installed.
Env Pass: Require python lib scipy version >= 1.1.0 installed.
Env Pass: Require python lib PIL version >= 5.3.0 installed.
Env Error: Require python lib networkx import testing failed, not installed.
Env Error: Get Require python lib networkx Version failed, please check build script.
Env Error: Require python lib networkx version >= 1.11 not installed.
Env Pass: Require python lib image version >= 1.5.5 installed.
Env Pass: Require python lib lmdb version >= 0.93 installed.
Env Pass: Require python lib onnx version >= 1.6.0 installed.
Env Pass: Require python lib h5py version >= 2.10.0 installed.
Env Pass: Require python lib flatbuffers version >= 1.10 installed.
Env Pass: Require python lib matplotlib version >= 2.1.0 installed.
Env Pass: Require python lib dill version >= 0.2.8.2 installed.
Env Pass: Require python lib ruamel.yaml version >= 0.15.81 installed.
Env Pass: Require python lib ply version >= 3.11 installed.
Env Pass: Require python lib torch version >= 1.2.0 installed.
Env Error: Env check FAILED!!!
- libcudart.so.10.1 没找到是因为Tensorflow-gpu 2.0.0 以上 开始 需要 CUDA10.1,这个报错可以不用管。
- networkx version >= 1.11 not installed,这里其实 networkx 是确认已经安装了的,但是 check 失败了,在确定正常安装的前提下,可以忽略这个 check 错误。
模型转换
转换工具的demo目录下有amlogic提供的转换demo,可以使用这个demo先验证环境是否搭建成功,在demo中有三个脚本,可以按照如下顺序依次执行。
第一个脚本,导入模型
$ ./0_import_model.sh
...
D Optimizing network with conv2d_big_kernel_size_transform
D Optimizing network with auto_fill_zero_bias, auto_fill_tf_quantize, align_quantize, broadcast_quantize, qnt_adjust_coef, qnt_adjust_param
I End importing tensorflow...
I Dump net to mobilenet_tf.json
I Save net to mobilenet_tf.data
I ----------------Error(0),Warning(0)---------------- #正常执行结束
...
第二个脚本,模型量化
$ ./1_quantize_model.sh
...
I Dump net quantize tensor table to mobilenet_tf.quantize
I [TRAINER]Quantization complete.
[TRAINER]Quantization complete.
I Save net to mobilenet_tf.data
I Clean.
I ----------------Error(0),Warning(0)---------------- #正常执行结束
...
第三个脚本,生成 case 代码
在执行第三个脚本生成case代码之前需要修改下脚本中的 optimize 参数内容,否则在运行时模型加载会出错,对于A311D而言,optimize 参数的值应为 VIPNANOQI_PID0X88
...
$export_ovxlib \
--model-input ${NAME}.json \
--data-input ${NAME}.data \
--model-quantize ${NAME}.quantize \
--reorder-channel '0 1 2' \
--channel-mean-value '128 128 128 128' \
--export-dtype quantized \
--optimize VIPNANOQI_PID0X88 \ #注意 A311D此处应修改为 VIPNANOQI_PID0X88
--viv-sdk ${ACUITY_PATH}vcmdtools \
--pack-nbg-unify \
...
然后执行脚本
$ ./2_export_case_code.sh
...
I Save vx network source file to /home/rpdzkj/acuity-toolkit-binary-5.21.1/demo_nbg_unify/.project
/home/rpdzkj/acuity-toolkit-binary-5.21.1/demo_nbg_unify
customer:input,0,1:output,0,0:
*********************************
/home/rpdzkj/acuity-toolkit-binary-5.21.1/demo
/
/home/rpdzkj/acuity-toolkit-binary-5.21.1/demo_nbg_unify
I ----------------Error(0),Warning(0)---------------- # 正常执行结束
...
模型转换完成后会在demo的当前目录与上层目录分别产生 normal_case_demo 和 demo_nbg_unify 两个目录
normal_case_demo :加载模型时,会有编译时间,耗时较长。
demo_nbg_unify : 在线编译已经由PC端完成,板子上能够直接加载nb文件,模型加载速度快。
转换自己的模型,可以将模型放到该目录下,然后修改 sh 脚本中的参数即可。
case 编译与运行
编译case代码需要使用到 DDK_6.4.6.2_SDK_V0.1 编译环境,开发板上默认有编译环境,DDK所在位置为 ~/DDK_6.4.6.2_SDK_V0.1/buildroot_sdk_646/
。
将case代码push到该路径下,默认已经有了一个 demo_nbg_unify 目录。复制的时候需要注意重命名。假设重命名为 demo_nbg_unify_convert
$ cp demo_nbg_unify/build_vx.sh demo_nbg_unify_convert/
然后进入 demo_nbg_unify_convert 目录下进行编译
$ ./build_vx.sh arm64
编译成功后会生成 bin_r 目录。
运行case代码
$ ./bin_r/mobilenettf network_binary.nb attach_input_out0_1_out0_1_224_224_3.tensor
Create Neural Network: 23ms or 23339us
Verify...
Verify Graph: 1ms or 1060us
Start run graph [1] times...
Run the 1 time: 6.00ms or 6033.00us
vxProcessGraph execution time:
Total 6.00ms or 6075.00us
Average 6.07ms or 6075.00us
--- Top5 ---
813: 0.999023
405: 0.000266
868: 0.000135
896: 0.000108
0: 0.000000
如果运行提示缺少库文件,可以在 buildroot_sdk/build/so/drivers_64_exportdata/
目录下找到。将里面的库文件全部复制到 /usr/lib/
目录下即可。