Zynqnet(二)算法设计

论文地址:https://github.com/dgschwend/zynqnet/blob/master/zynqnet_report.pdf

摘要:该论文核心内容从第三章开始依次介绍了CNN的优化分析和训练,第四章FPGA加速器的设计和实现,第五章实验结果和分析。关于cnn的优化分析和训练部分,不是本博文介绍的重点,需要一些深度学习知识支撑,重点介绍一下FPGA端的实现知识。

4.2算法设计

4.2.1 需求分析

• convolutional layers

  • – kernel size 1×1, padding 0
  • – kernel size 3×3, padding 1
  • – stride 1 or stride 2

• ReLU nonlinearities
• concatenation
• global average pooling

以上内容为FPGA端需要实现的操作。

4.2.2 算法设计

给出了多通道下卷积计算的公式。然后分析了三种卷积计算的方法:

  • Matrix Multiplication 使用gemm函数,将输入输出转化为矩阵乘法的计算
  • Fast Fourier Transformation 快速傅立叶变换
  • Sliding-Filter 2D Convolution Approach 卷积计算直观理解上的滑窗计算方法

Zynqnet选择使用最后一种卷积计算方法,然后给出了自己的算法,实现输入图片经过神经网络进行计算的功能。

按照如下计算顺序:

每个卷积层:

        行高(二维上的Y):

               行宽(二维上的X):

                       输入通道(输入特征):<~~(x,y)位置上所有的输入通道

                               输出通道(有多少个卷积核就有多少个输出通道,对每个卷积核对应位置的权值):

                                      卷积核窗口计算:

                                    

4.2.3 并行分析

FPGA的优点就是用电路实现并行计算,然后论文对可以并行计算的部分进行讨论:

• independence of layers when applied to different image frames 不同的图片之间没有依赖可以并行,但是这里不考虑这个。
• independence of dot-products at different pixel positions (y, x)  不同目标位置的点积计算求解没有依赖
• independence of input channels ci 多个输入通道可以同时进行卷积
• independence of output channels co 多个输出通道可以同时求解
• independence of intra-kernel multiplications 卷积计算本身的并行

基于以上分析确定最终的并行策略

  • 3×3卷积核做卷积时,并行9次乘法8次加法使用加法树实现该功能;
  • 利用不同的输出通道并无依赖,部分展开Co 循环(输出通道循环),控制因子为Npe.即一次计算位置x,y处的Npe个输出通道。这对应着本篇文章第一副插图中的第一步,参与计算的输入特征为(x,y,ch_in),及其周围共9个像素,权值可以取ch_out个卷积核对应通道的权值。但是受限于计算资源,这里的并行只采用Npe个。即并不一次性取所有的ch_out,只是去Npe个,所以要求ch_out要是Npe的整数倍。实现了对于一个输入特征(x,y,ch_in)处,同时计算Npe个卷积核,然后,对所有的ch_out计算完成之后,ch_in累加1,再重复Npe个卷积核窗口计算。

4.2.4 数据复用

on-chip memory不足以保存所有的输入输出和权值参数,通过使用板上数据的复用来减少和外部存储之间的读写,所有的内存读取操作都应该是线性的(就是需要同时被读取的数据应该像数组一样保存在连续的地址中),便于是进行突发模式的数据传输,需要进行缓存的数组包括:

  • 输入特征,算法line22
  • 输出特征, 算法line30 32
  • 权值, 算法Line23

这张图示了Linebuffer的缓存数据。我并没有搞懂这其中的原理,先放下。

根据以上分析,确定如下的缓存策略:

  • Image Cache (ICache) :line buffer。一些参数的解释:256 最大像素宽度;736最大通道数;因为通道数可以分离,这里先保证宽度的需求,256×32 = 8192, 可以理解为缓存32个输入通道的一行的像素。这里设置一个 image line,也就是一个输入特征图(多个通道)的一行,最大为8192个像素。图示要求2个多行,这里选用4个Linebuffer,因此为8192×4=32 768
  • Output Cache (OCache) :某个输出位置上的,多通道buffer。可以使用突发模式进行传输
  • Global Pooling Cache (GPoolCache)  类似于OCache,最后进行全局池化的时候保存中间累加结果。
  • Weights Cache (WCache)  消耗最大的一种缓存,某层的权值所含参数的数量为 Ci×Co×9。以Fire8层为例,384 × 112 × (3 × 3) = 387 072 为权值,外加112个bias = 387184, Fire10为例,736×512×(1×1) =376 832 + 512 = 377344。本论文实际使用的缓存数量为16 × 3 × 1024 × 9 = 442 368

综上,一次读取像素in[L, y, x, ci],一次读取权值W[L, co, ci],得到Co个通道中x,y位置处的计算结果。因此以上算法合理。

 

参考:

板上硬件资源 https://www.xilinx.com/support/documentation/data_sheets/ds891-zynq-ultrascale-plus-overview.pdf

突然 https://blog.csdn.net/qwaszx523/article/details/52351282


版权声明:本文为crazyeden原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。