树莓派运行yolo fastest优化
前言
yolo fastest的ncnn例子中,第一版默认启用bf16s加速,但是最近的版本并没有启用。
主要做了如下优化
1.更改树莓派系统为Raspbian-64位
2.启用ncnn的bf16s加速
第一部分—安装Raspbian-64位系统
一,下载镜像和工具
1.镜像下载
树莓派64位镜像文件
2.SD Card Formatter下载
SD Card Formatter
3.烧录工具下载
win32DiskImager
二,烧录系统
这一部分省略,和网上大部分操作一样。
三,增加wifi连接配置和ssh服务
SD卡插入电脑(暂时不要插入树莓派),打开boot盘,在根目录下新建两个文件,wpa_supplicant.conf和ssh。ssh文件为空文件,向wpa_supplicant.conf文件中写入接下来要连接的wifi信息,格式如下:
country=CN
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="wifi名称"
psk="WiFi密码"
key_mgmt=WPA-PSK
priority=1
}
network={
ssid="WiFi-B"
psk="12345678"
key_mgmt=WPA-PSK
priority=2
scan_ssid=1
}
保存后,拔卡插入树莓派,通电等候连接wifi。然后通过路由器获得ip地址。
四,更改镜像源
利用putty等工具登录树莓派后,输入
备份原始镜像
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
查看
sudo vi /etc/apt/sources.list
将原始镜像全部删除,修改为:
deb http://mirrors.tuna.tsinghua.edu.cn/debian buster main contrib non-free
deb http://mirrors.tuna.tsinghua.edu.cn/debian-security/ buster/updates main contrib non-free
deb http://mirrors.tuna.tsinghua.edu.cn/debian buster-updates main contrib non-free
# Uncomment deb-src lines below then 'apt-get update' to enable 'apt-get source'
#deb-src http://mirrors.tuna.tsinghua.edu.cn/debian buster main contrib non-free
#deb-src http://mirrors.tuna.tsinghua.edu.cn/debian-security/ buster/updates main contrib non-free
#deb-src http://mirrors.tuna.tsinghua.edu.cn/debian buster-updates main contrib non-free
再将输入
sudo vi /etc/apt/sources.list.d/raspi.list
修改为
deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui
更新一下
sudo apt-get update
sudo apt-get upgrade
完成镜像修改!
五,下载桌面
sudo apt-get install xrdp
之后重启一下树莓派
sudo reboot
六,远程桌面连接
win10中搜索程序:远程桌面连接
输入ip地址后,进入登录界面。登录账号:pi ;密码:raspberry。
既可进入树莓派桌面系统。如图
第二部分—yolo-fastest优化
一,选用ncnn作为基础部署框架
这一部分参考:yolo-fastest ncnn部署
二,启用bf16s优化
1.参考
对于类似树莓派等小型设备,算力不强,需要减少计算量。这一部分主要参考:https://github.com/Tencent/ncnn
在faq.md文件中中有两句话介绍
net.opt.use_packing_layout = true;
net.opt.use_bf16_storage = true;
以及参考https://zhuanlan.zhihu.com/p/112564372
但是刚开始看有点懵逼!
2.实例参考
从上面两句中看到主要是找到这两句指令的具体操作位置,在ncnn库中,有一个examples文件夹,里面有很多ncnn实现的例子,在yolov5.cpp文件中存在:
ncnn::Net yolov5;
yolov5.opt.use_vulkan_compute = true;
// yolov5.opt.use_bf16_storage = true;
分析应该是在初始化网络处添加net.opt.use_bf16_storage = true;既可。
以及在yolov4.cpp的56行处
yolov4->opt.use_packing_layout = true;
也是在初始化网络处添加该指令。
3.yolo-fastest中启用bf16
兜兜转转,该说正事了。
打开sample/ncnn/src/YoloDet.cpp文件
网络初始化处添加上述指令,关键字YoloDet::init。
#include "YoloDet.h"
ncnn::Net DNet;
static ncnn::PoolAllocator g_blob_pool_allocator;
static ncnn::PoolAllocator g_workspace_pool_allocator;
int YoloDet::init(const char* paramPath, const char* binPath)
{
DNet.opt.use_packing_layout = true;
DNet.opt.use_bf16_storage = true;
printf("Ncnn mode init:\n %s \n %s\n", paramPath, binPath);
g_blob_pool_allocator.clear();
g_workspace_pool_allocator.clear();
g_blob_pool_allocator.set_size_compare_ratio(0.0f);
g_workspace_pool_allocator.set_size_compare_ratio(0.0f);
DNet.load_param(paramPath);
DNet.load_model(binPath);
return 0;
}
int YoloDet::detect(cv::Mat& srcImg, std::vector<TargetBox>& dstBoxes)
{
//DNet.opt.use_packing_layout = true;
//DNet.opt.use_bf16_storage = true;
ncnn::Mat in = ncnn::Mat::from_pixels_resize(srcImg.data, ncnn::Mat::PIXEL_BGR2RGB,\
srcImg.cols, srcImg.rows, IW, IH);
//Normalization of input image data
const float mean_vals[3] = {0.f, 0.f, 0.f};
const float norm_vals[3] = {1/255.f, 1/255.f, 1/255.f};
in.substract_mean_normalize(mean_vals, norm_vals);
//Forward
ncnn::Mat out;
ncnn::Extractor ex = DNet.create_extractor();
ex.set_num_threads(NUMTHREADS);
ex.input("data", in);
ex.extract("output", out);
//doresult
dstBoxes.resize(out.h);
for (int i = 0; i < out.h; i++)
{
const float* values = out.row(i);
dstBoxes[i].cate = values[0];
dstBoxes[i].score = values[1];
dstBoxes[i].x1 = values[2] * srcImg.cols;
dstBoxes[i].y1 = values[3] * srcImg.rows;
dstBoxes[i].x2 = values[4] * srcImg.cols;
dstBoxes[i].y2 = values[5] * srcImg.rows;
}
return 0;
}
修改后重新编译,运行一下
sh build.sh
./demo
可以看到速度有一定的提高,但是还存在问题,我没有开启bf16s时,每一帧用时大概是120ms;开启后100ms。
三,查看cpu运行情况
cpu运行情况如下,可以看到没有使用多少。
继续查找原因,在sample/ncnn/src/include/YoloDet.h中,有一句代码,指定运行cpu线程数,原始值为8,但是树莓派4b是四核的,因此修改为4.测试发现修改小数值,速度还快了。并重新编译运行。结果达到qiuqiu大佬在树莓派4b上的效果。