Skip to content

xbdxwyh/yolov3_fpga_project

Repository files navigation

yolov3_hls

这一块的代码是在把上交的陈辰大佬的yolov2代码改成yolov3的时候的一些改动,主要步骤还是参考陈辰大佬的代码。 https://github.com/dhm2013724/yolov2_xilinx_fpga 但是有一些和他不一样的细节。

Tips:

我目前已经不做这个方向了,有些细节记得不是很清楚了,只能把当时的复现实验报告和做v3时候的细节报告传上来(请忽略掉一些吐槽),请分别查看v2和v3的pdf报告。

在权重处理部分

在权重处理部分我写了好几个版本的,由于过去了一段时间,我也忘记了当初用的哪一个版本了。 但是主要的改动在于内存控制的部分,在第2步的第一小步骤:产生重组织的权重的时候,进行了修改。 在第二步的第二个小步骤,产生量化的文件只进行了偏移量的修改,此外为了和我的实验匹配还加了一些垃圾代码,你可以不看(比如固定位数的量化) 在第三步产生输入输出的特征图量化的步骤同样进行了上述步骤的修改。[但是事后才发现有很大的问题,这一块的补偿体现在了elf代码里,在对卷积层判定的时候对于层号的选择那块]

IP核部分

IP核的改动不算特别大,移除了YOLOv2的maxpool部分,增加了shortcut(add方式的)和upsample层。 同时对于upsample层的块大小做了固定[尝试增加块大小到26(最小的二倍),但是发现性能低到爆炸] 由于记性不好,我忘记了生成ipcore使用的是yolov3.cpp还是cnn.cpp了

最终的elf部分

由于以上的种种问题,在这块的代码上缝缝补补改了很多。 首先是由于shortcut选择了对其的方式,所以会因为不同层之间的量化位数不同产生溢出,因此需要把输出较大的层和输出较小的层做同步。[比如A层有输出13.6,A+3层有输出0.01,获得A层的位数是10,A+3是15,这个时候shortcut如果向A+3层的位数同步,那么就会造成13.6*pow(2,15)产生超过16位的结果] 其次由于yolov3有比较复杂的FPN机制,所以需要保存很多层的信息,因此我的缓存区利用的并不好[虽然后面重写了一个版本的,但是在fpga上好像并不行我也不知道是什么原因,业已证明只需要5个小缓冲区就能做完yolov3,我这里相当于用了十个] 同样的,由于缓冲区设计以及IPcore的设计,在并不需要做route层的情况下就可以实现[使用地址直接拼接,反正route也是拼接] [实际上在fpga做upsample并不快,只是少了因为拷贝内存的时间,所以相对于总时间来说这一块也放fpga上了]

最终的效果

其实并不怎么好,因为陈辰大佬使用了im2col的方式进行计算,而yolov3过深的网络结构给arm核的拷贝带来了大量的负担,为了拷贝数据造成的时延实际上相当大。 但是最终的能耗确实很低。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published