首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

嵌入式深度学习之神经网络二值化(3)-FPGA实现

本文系微信公众号《大话计算机视觉》,原创文章,转载请注明出处。

前两篇文章介绍了二值化神经网络和异或神经网络,本篇将侧重介绍二值化神经网络的FPGA实现。

在最近两年,深度神经网络已经被应用在各种领域了,比如智能手机,智能安防,智能家居。在嵌入式端,神经网络有部分部署在基于CPU+DSP/GPU架构的硬件系统,部分用上了FPGA和ASIC。对于CPU+DSP/GPU来说,网络架构的灵活性是最大的,而且支持高精度的神经网络,易于实现扩展,控制成本。但是对于实际的消费电子应用场景对神经网络的实时性(Real-time),能耗和延时性(Latency)要求比较高,在这种情况下,CPU+DSP/GPU的优势就没有FPGA和ASIC明显了。FPGA相对于ASIC来说,灵活性高了不少,开发周期也缩短了,而且多数ASIC前期也是使用FPGA进行验证。

神经网络因其网络特性(multiplelayers and multiple feature maps per layer),对于并行化(Parallel)和流水线化(Pipeline)有着巨大的需求。尽管GPU能提供并行化和流水线处理,但是延时和功耗上比FPGA差的比较多。FPGA上对于神经网络上的每个乘加器(MAC)可以定制化为一个模块(Block),可以将每个模块进行并行化和流水线处理。这已经大大的加快了神经网络的处理速度但是还不足够。

FPGA内的逻辑元件包括:与门、或门、非门、三态门、加法器、乘法器。但是并不是所有的逻辑器件的运算效率的都一样。当神经网络二值化以后,乘加器(MAC)可以被更简单的异或门和按位计数(XORand bit count)所代替,在牺牲一定精确度的条件下,换取了巨大的算力增长和功耗减少。随着HLS High level synthesis一种在高层次将算法转化为电路描述方法的发展,越来越容易将C语言等高级语言转换成FPGA的实现。也使得神经网络在FPGA的验证变得更简单。

在FPGA2017和FPGA2018顶会上有很多团队介绍了各自FPGA神经网络加速器的成果,本文摘选了其中一篇文章来作为二值化卷积神经网络的FPGA实现的介绍。大家这可以在文章底部找到原文。大家不仅可以熟悉之前

这篇论文主要工作是基于xilinx的Zedboard FPGA实现了二值化神经网络的推理部分(inference),用HLS设计方法来开发,源代码在github(https://github.com/cornell-zhang/bnn-fpga)上可以查阅。本论文选取了一个比较简单的二值化神经网络来做实现,如下图,包含6个卷积层,3个池化层和3个全连接层。用于做Cifar-10的分类任务。

该神经网络的具体结构和权重的比特数计算如下图所示,整个神经网络使用了13.4Mbits(~1.675MB)的权重,卷积层和全连接层分别占4.36Mbits(~0.545MB)和9.01Mbits(~1.126MB)。全连接层由于是点对点的连接,需要的权重比较多,8192x1024+1024x1024+1024x10=9.01Mbits。另外可以注意到输出的最大维度是128Kbits,但是一层的权重最大可以消耗2.3Mbits。权重的计算后面我们可以找一个例子详细分析。

下图介绍了一般卷积神经网络和二值化卷积神经网络中卷积层处理的区别,相对比卷积神经网络,二值化神经网络的卷积层省略了偏置和激活函数,加入了批标准化和二值化,并且接收的输入是二值化输入数据。

这里需要注意是本文的二值化神经网络做完卷积操作以后就进行池化,卷积的结果是整型,针对池化的结果来做批标准化,批标准化是基于整型来做的。通过线性平移来保证输入分布的均值为,方差为1,这样尽可能减少输入的损失,然后进行二值化处理,得到这一层的输出。

相比于高精度卷积神经网络,在FPGA上使用二值化神经网络的优势有两点:

1,传统卷积神经网络的乘积(MAC)操作被二值化神经网络中的按位异或(bitwise XNOR)操作所取代,更适合于FPGA中LUT的实现。

2,在同等多的特征图和全连接层的情况下,二值化权重和二值化特征图极大降低了内存的大小,突破了片内和片外的内存访问带宽。这降低了FPGA的实现难度。

针对硬件设计,本文的使用了三个优化技巧:

1,通过实验表明,偏置项设为以后对于测试精度的影响不大,Test error为11.32%。

2,在批标准化中,引入了线性变换,y=kx+h,其中k和h被量化为16bit精度,适合做平移操作,同时对输入的浮点型进行定点化。

3,在原有的网络中,对边界使用了零填充,但是在二值化神经网络里面,没有,只有+1,-1,所以这里使用+1去填充边界。对于精度影响不是很大。但是在FPGA实现里面,考虑到资源问题,还是使用了零填充。

整个FPGA系统架构图如图(a)所示,主要由三个计算单元,一个数据缓冲区,一个DMA加上一个FSM的控制器组成。三个计算单元分别是FP-Conv,针对第一层非二值化的输入。Bin-Conv是二值化的卷积操作,Bin-FC是二值化的全连接操作。

之前提到了,二值化神经网络里面特征图的最大维度是128Kbits,对于中低端的FPGA来说,是完全可以放在片上的,所以这里用了Buffer A和Buffer B来缓存每一层的输入和输出特征图,当Buffer A缓存输入时,Buffer B用来缓存卷积之后的输出,然后Buffer B作为输入给计算单元,Buffer A就用来缓存输出。以时间来换空间,这种架构latency比较大,可以算是串行架构,但是省了比较多的memory。对于权重来说,片上的memory是不够存储全部权重的,所以引入了param buffers来更新每一层用到的权重,通过DMA来衔接片内和片外的内存。

图(b)展示的是一个Bin-Conv的架构图,因为整个神经网络中,卷积层消耗了最多的计算资源和运算时间,为了达到神经网络加速的目的,卷积层的设计必须兼顾带宽和资源。这里引入了两个关键模块,一个是使用了可变位宽的行缓存(VWLB),一个是Bitsel位选择器。可变位宽的行缓存能支持最低8bit一个字节最高32bit一个字节的输入,保证了存储器的最大利用率,位选择器可以帮助缓存不同位宽的数据,存入不同的行缓存里面,也可以保证卷积和数据的对应。下图展示了Bitsel和Line Buffer工作的例子,当输入为32bit时,因为行缓存的最大位宽为32bit,Bitsel不做操作,直接存入每一行,当输入为8bit时,Bitsel会分别填充到行缓存里面,对应可以填充4行的8bit数据。

对于每个BitConv单元,包含两个行缓存bank和两个卷积器,对特征图进行乒乓存储,然后分别做卷积,提升了位卷积模块的吞吐量。

具体实现请参考github上的源码,HLS的code可以在xilinx的zynq7020平台上跑。论文作者用C++优化的模型和加速器的实现进行了对比,FPGAb并没有精度上的损失。对比python实现,FPGA的结果更好。

论文作者用四种不同的运算平台

1 FPGA: Zedboard with XC7Z020

2 Intel Xeon 8-core 2.6GHz CPU,

3 Nvidia Tesla K40 (1.7TFLOPS) GPU,

4 Nvidia Jeston TK1 (157GFLOPS) mGPU

进行对比。以NV的Jeston TK1作为参考,FPGA上加速了大概15倍,功耗大概4.7W。

总的来说,FPGA上的加速相比于CPU和mGPU来说,速度,功耗和成本上都有明显的优势。进一步,FPGA作为神经网络的原型验证,易于porting到ASIC实现,如果产品的需求比较大,是很适合将FPGA原型转化为ASIC的。

Paper: http://www.csl.cornell.edu/~zhiruz/pdfs/bnn-fpga2017.pdf

Github: https://github.com/cornell-zhang/bnn-fpga

先加个宣传,请大家通过下面二维码关注大话计算机视觉公众号。关注发送“资源共享” 可以或者电子书,论文,训练数据集等持续更新数据

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180703G02LC900?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券