【触觉智能Purple Pi开发板试用】移植ncnn神经网络推理框架
0x0 介绍Purple Pi和ncnn
IDO-SBC2D06主板,是基于SigmaStar SSD201 SoC(ARM CortexA7内核)兼容树莓派的开发板,主频高达1.2GHz,256KBL2-缓存,内置双MAC、一个PHY,支持双100M以太网接口等。内存管理支持DMA引擎。集成H.264/AVC和H.265/HEVC解码器,支持最大分辨率FHD(1920×1080)/60帧解码
https://github.com/Tencent/ncnn
NCNN作为业界首个为移动端优化的神经网络前向计算框架,在2017年首次开源,是腾讯优图实验室第一次对外公开深度学习的研究成果。目前多应用在图像方面,例如人像自动美颜,照片风格化,超分辨率,物体识别等等。NCNN计算框架,因其高性能、无第三方依赖、跨平台支持大部分常见CNN网络的特点,是许多开发者在移动端、嵌入式设备上部署深度学习算法的首选框架。
0x1 配置工具链
从github上直接clone sdk,其中包含工具链
git clone https://github.com/industio/PurPle-Pi-R1
需要先执行 install_toolchain.sh 脚本,否则会报错 cc 找不到
cd toolchain
sh install_toolchain.sh
0x2 交叉编译ncnn和跑分工具
从github上clone ncnn源码
git clone https://github.com/Tencent/ncnn
为purple pi工具链编写 purplepi.toolchain.cmake 放在 ncnn/toolchains 文件夹中
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
if(DEFINED ENV{TOOLCHAIN_ROOT_PATH})
file(TO_CMAKE_PATH $ENV{TOOLCHAIN_ROOT_PATH} TOOLCHAIN_ROOT_PATH)
else()
message(FATAL_ERROR "TOOLCHAIN_ROOT_PATH env must be defined")
endif()
set(CMAKE_C_COMPILER "${TOOLCHAIN_ROOT_PATH}/bin/arm-linux-gnueabihf-gcc")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_ROOT_PATH}/bin/arm-linux-gnueabihf-g++")
set(CMAKE_FIND_ROOT_PATH "${TOOLCHAIN_ROOT_PATH}/arm-linux-gnueabihf")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon")
set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
进行交叉编译,其中有编译选项
- -DNCNN_OPENMP=ON 开启多线程支持
- -DNCNN_SIMPLEOCV=ON 开启图像编解码支持
- -DNCNN_BUILD_EXAMPLES=ON 编译内置的示例
export TOOLCHAIN_ROOT_PATH=/home/nihui/osd/PurPle-Pi-R1/toolchain/gcc-arm-8.2-2018.08-x86_64-arm-linux-gnueabihf
mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/purplepi.toolchain.cmake -DCMAKE_BUILD_TYPE=release -DNCNN_OPENMP=ON -DNCNN_SIMPLEOCV=ON -DNCNN_BUILD_EXAMPLES=ON ..
make -j4
编译好后,会在 build/benchmark 中找到跑分工具 benchncnn
0x3 上板跑分
microusb线链接开发板和电脑,自动获得 ttyUSB0 设备,tio串口访问
tio /dev/ttyUSB0
修改 /etc/wpa_supplicant.conf 保存wifi ssid和密码,然后 wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf -B &
连接wifi
就能用 ssh 连上开发板了,不再需要用串口
由于这个开发板内存较小,不足以跑过大部分模型,因此修改 ncnn/benchmark/benchncnn.cpp 只留下这次评估的 FastestDet 模型
benchmark("FastestDet", ncnn::Mat(352, 352, 3), opt);
杀死两个吃cpu和内存的进程,释放更多资源
killall disp_init
killall app_music
将跑分工具benchncnn和模型配置 scp 上传到开发板
scp benchncnn root@192.168.31.188:/root/
scp ../../benchmark/FastestDet.param root@192.168.31.188:/root/
启动 benchncnn 会报错找不到 libgomp.so.1
# ./benchncnn
./benchncnn: error while loading shared libraries: libgomp.so.1: cannot open shared object file: No such file or directory
这时候,需要把工具链中 sysroot/lib/libgomp.so.1 也一起上传到开发板,这是openmp多线程运行时库
scp PurPle-Pi-R1/toolchain/gcc-arm-8.2-2018.08-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib/libgomp.so.1 root@192.168.31.188:/root/
再次执行 benchncnn,可以看到 FastestDet 在2线程加速下,耗时约 192ms
# ./benchncnn 4 2 0 -1 0
loop_count = 4
num_threads = 2
powersave = 0
gpu_device = -1
cooling_down = 0
FastestDet min = 191.45 max = 193.48 avg = 192.35
0x4 开启bf16加速
这款开发板内存较小,同时内存性能也较弱,可以开启ncnn内置的bf16加速开关,进一步降低神经网络推理的内存占用,以及降低内存访存量
在 benchncnn.cpp 中添加这行代码
opt.use_bf16_storage = true;
在开启 bf16 后可以跑更多模型,同时 FastestDet 也比 fp32 模式下进一步加速到 149ms
# ./benchncnn 4 2 0 -1 0
loop_count = 4
num_threads = 2
powersave = 0
gpu_device = -1
cooling_down = 0
squeezenet min = 268.62 max = 275.13 avg = 270.30
mobilenet min = 444.71 max = 445.38 avg = 444.95
shufflenet min = 147.60 max = 148.06 avg = 147.81
FastestDet min = 149.48 max = 150.37 avg = 149.77
这个耗时数据在 ncnn 小板子榜单中,名次较后 :D
https://github.com/nihui/ncnn-small-board
tbd 下一篇文章将介绍 FastestDet 目标检测应用