Optimizing the Convolution Operation to Accelerate Deep Neural Networks on FPGA
论文原文: Ma, Y., et al. (2018). “Optimizing the Convolution Operation to Accelerate Deep Neural Networks on FPGA.” IEEE Transactions on Very Large Scale Integration (VLSI) Systems 26(7): 1354-1367.
摘要
1. 作者想要解决什么问题
卷积加速方案会显著影响CNN加速器的效率和性能。卷积涉及具有四个循环级别的乘法和累加运算,这带来了较大的设计空间。但先前的工作要么采用有限的循环优化技术,例如循环展开(unrollilng),分块(tilling)和交换(interchange),要么仅在加速器体系结构和数据流已经固定之后才调整一些设计变量。最终的加速器几乎无法利用数据重用并有效地管理数据移动。
2. 通过什么理论或者模型来解决
本文通过基于多个设计变量定量分析和优化CNN加速器的设计目标(例如内存访问)来克服上述障碍。然后,本文提出了硬件CNN加速的特定数据流,以最大程度地减少数据通信,同时最大化资源利用率以实现高性能。
3. 给出了什么答案
通过实现包括NiN,VGG-16和ResNet-50 / ResNet152的端到端CNN进行推理,演示了提出的CNN加速方案和体系结构。对于VGG-16 CNN,在Intel Stratix V和Arria 10 FPGA上,总体吞吐量分别达到348 GOPS和715 GOPS.
I. 引言
1.研究背景
现代FPGA允许定制架构,并可以利用数百到数千个片上DSP模块。但是,在将CNN映射到FPGA上仍然存在重大挑战。
深度CNN算法具有数十到数百个层,在大小和配置方面,各层之间存在显着差异。 FPGA上有限的计算资源和存储容量使CNN的最佳映射任务(例如,使受能耗限制的延时最小化,或者相反)成为一个复杂的多维优化问题。片外通信的高成本是实现更高性能和更低能耗的另一个主要障碍。实际上,与大量数据移动和存储器访问相关的能源成本通常超过了计算的能源消耗。由于这些原因,基于FPGA的高能效CNN硬件加速需要同时最大化资源利用和数据重用,以及最小化数据通信。
2. 研究现状
在CNN中,卷积由沿着kernel和特征图滑动的四个level的循环执行,如图1所示。这产生了一个庞大的设计空间,其中包括用于:实现并行性,计算顺序和对大数据集进行划分的各种选择,将数据分成较小的块以适合片上存储器等。这些问题可以通过现有的循环优化技术]处理,例如循环展开,分块和交换。
尽管已经有加速器采用了这些技术,但是尚未对这些技术对设计效率和性能的影响进行系统和充分的研究。如果没有充分研究卷积的循环操作,就很难为高吞吐量的CNN实现有效地自定义数据流和体系结构。
3. 基于哪些假设
CNN中超过90%的运算都涉及卷积操作。因此,有理由认为,加速方案应侧重于并行计算的管理以及跨多个级别的存储器(例如,片外动态随机存取存储器(DRAM),片上存储器和 本地寄存器)的数据存储和访问的组织。
- 我们对卷积运算的三种循环优化技术进行了深入分析,并使用相应的设计变量对加速方案进行了数值表征。
- 根据设计变量的配置,定量估算CNN加速器的设计目标(例如延迟,访存)。
- 提出了一种有效的卷积加速策略和数据流,旨在最小化数据通信和内存访问。
- 数据路由(data router)的设计目的是处理卷积滑动操作(例如stride和padding)的不同设置,尤其是对于高度不规则的CNN。
- 设计了一种相应的硬件体系结构,该体系结构充分利用了计算资源以实现高性能和高效率,并且对于所有层而言都是统一且可重复使用的。
II. 卷积的加速–关键设计变量
1. 通用的CNN加速器系统
CNN算法设计大量数据和权重,片上存储不足以存储所有数据。因此,典型的CNN加速器包括三个层次的存储层次结构:1)外部存储器; 2)片上缓存;3)PE关联的寄存器
基本流程是将数据从外部存储器获取到片上缓冲器,然后将其馈送到寄存器和PE中。 PE计算完成后,结果将传输回片上缓冲区,并在必要时传输到外部存储器,这些数据将用作后续层的输入。
2. 卷积循环
卷积是由四个级别的循环实现的,如图1中的伪代码所示,如图3所示。为了有效地映射和执行卷积循环,可以使用三种循环优化技术,即循环展开(unrolling),循环分块(tilling)和循环交换(interchange)用于定制具有三个级别的内存层次结构的加速器的计算和通信模式。
3. 循环优化和设计变量
图3使用多个维度(dimensions)描述给定CNN的每个卷积层的特征图和卷积核尺寸。循环展开和循环分块的硬件设计变量将确定加速因子和硬件占用空间。表I列出了本文中使用的所有dimensions和variables。
| 符号 | 意义 | 符号 | 意义 |
|---|---|---|---|
| 卷积窗宽度 | 卷积窗高度 | ||
| Input Feature宽度 | Input Feature高度 | ||
| Output Feature宽度 | Output Feature高度 | ||
| Input Features数量 | Output Features数量 |
循环展开设计变量,它们表示并行计算的次数。
循环分块设计变量,他们表示存四个循环中,存储在片上缓存的数据部分。
这些dimensions或者variables具有如下的约束条件。
输入和输出的变量的关系受(1)-(3)约束
1.1 循环展开
如图4-7所示,展开不同的卷积循环会导致不同的计算并行化,这会影响有关数据重用机会和内存访问模式的最佳PE体系结构。
- Loop-1:在一个cycle内同时计算同一特征图和统一卷积窗中不同位置(数量)的像素, 相当于并行一个卷积窗的不同元素.
- Loop-2:同时计算数量的,来自不同特征图/kernel, 同一位置的乘法. 相当于多个特征图同时做卷积.
- Loop-3:在每个周期中,将来自相同特征图中不同(x,y)位置的(数量)像素数乘以相同的权重, 因此,该重量可以重复使用次. 相当于同一卷积窗卷积同一图像不同位置.
- Loop-4:在每个周期中,输入特征图的一个像素乘以相同(x,y)位置处, 但来自不同的Kernel的数量的权重,并且该像素被重用次。相当于多个卷积窗卷积同一个特征图.
四个卷积循环的展开变量值共同确定并行MAC操作的总数以及所需乘法器数量(Pm)
1.2 循环分块
循环展开用于将整个数据划分为多个块,这些块可以容纳在片上缓存中,如图8所示。通过正确分配循环切片大小,可以增加数据的位置以减少DRAM访问的次数。
循环分块决定了片上缓存的下界:
-
输入像素buffer的大小至少为:
-
权重buffer的大小至少为:
-
输出buffer的大小至少为:
1.3 循环交换
循环交换确定四个卷积循环的顺序计算顺序。循环交换有两种,即Intratile(tile内)和Intertile(tile间)循环顺序。
- Intratile循环顺序决定了从片上缓冲器到PE的数据移动方式。
- Intertile循环顺序确定了数据从外部存储器到片上缓冲器的移动。
III. 硬件加速设计目标的定量分析
1. 计算延时
每层乘法操作数量()
理想情况下,每层的计算周期数应为,而是乘法器数量。但是,对于不同的循环展开和分块大小,不一定必须对每个卷积维度都能充分利用乘法器。每层的实际计算周期数为
其中的表示向上取整
在这里,我们假设乘法器连续接收输入数据而没有空闲周期。如果N∗与T∗的比率或T∗与P ∗的比率不是整数,则乘法器或外部存储器transaction未得到充分利用。除了考虑计算延迟之外,还必须考虑整个系统延迟的内存传输延迟。
2. 部分和存储
部分和(partial sum)有时需要在接下来的几个周期中存储在内存中,有时必须在PE之间移动。有效的加速策略必须使部分和的数量最少,并尽快在本地进行处理以减少数据移动。
计算存储在存储器中的部分和(#psum)的流程图如图9所示
Loop1和loop2全展开时没有部分和,可直接写回DRAM.
P *或 T *确定的部分和的数量很小,可以存储在本地寄存器(9.2)中。 或片内缓冲器(9.3)。
如果loop tile不能包含Loop-1和Loop-2的所有数据,则需要将一个tile的部分和存储在片上或片外存储器中,直到被另一tile消耗为如(9.6)-(9.9)所示。
总结下来就是, 循环的计算顺序也会影响部分和的数量,并且循环1和Loop-2的计算越早,部分和的数量就越少。将部分和存储在不同级别的存储器层次结构中的要求极大地恶化了数据移动和相关的能源成本。
3. 数据复用
重用的两种类型:
- 空间重用(Spatial Reuse):意味着从片上缓冲器读取数据后,单个像素或权重将在一个时钟周期内用于多个并行乘法器。
- 时间重用(Temporal Reuse):时间重用意味着单个像素或权重用于多个连续周期。
每个周期具有Pm个并行乘法运算需要将Pm像素和Pm权重馈入乘法器。每个周期所需的d权重数为
如果Loop-1没有展开,则每个周期所需的不同像素数
权重在一个周期内在空间上重复使用的次数为
通过展开Loop-3或实现权重的空间重用。像素的数量在一个周期内在空间上被重用(Reuse_px)为
如果未展开Loop-1,则Reuse_px为
否则, Reuse_px为
4. 片上访存
利用数据重用,可以显着减少片上缓冲区访问的次数。由于没有任何数据重用,因此片上缓冲器对像素和权重的总读取操作为Nm,因为每次乘法都需要一个像素和一个权重。通过数据重用,片上缓冲器读取权重的总数变为
像素的读取操作总数为
如果无法在一个图块内获得最终输出像素,则将其部分和存储在缓冲区中。每个周期的部分总和向缓冲区的读写操作数为,所有部分和都由Loop-1 ()产生, Loop-2()生成的乘积在乘法后立即求和。
将输出像素写入片上缓冲区的次数(即*#write_px*)与给定CNN模型中输出像素的总数相同。最后,片上缓冲区访问的总数为
5. 片外访存
DRAM访问的成本具有更高的延迟和能量, 通过具有足够大的片上缓冲区和适当的循环计算顺序,可以实现最少的DRAM访问次数,从而每个像素和权重仅需从DRAM传输一次。
估计DRAM访问次数的流程图如图10所示,其中*#DRAM_px和#DRAM_wt* 分别表示一个输入像素和一个权重的DRAM访问次数。
从DRAM中取出所有数据后,应将其全部耗尽,然后将其踢出缓冲区。
因此,如果图块大小或片上缓冲区可以完全覆盖一层的所有输入像素或所有权重,则可以在图10中以(10.8)实现最小DRAM访问。
通过首先计算Loop-3,如图10中的(10.1)和(10.5)中所示,重用了存储在缓冲区中的权重并减少了*#DRAM_wt*。
类似地,通过首先计算Loop-4,可以像(10.3)和(10.6)一样重用像素来减少*#DRAM_px*。但是,首先计算Loop-3或Loop-4可能会延迟Loop-1或Loop-2的计算,这将导致大量的部分和。
IV. State-of-the-art CNN加速器所使用的加速方法
当前设计的循环展开策略可以分为四种类型:
- [Type-A]展开loop-1,loop-2,loop-4
- [Type-B]展开loop-2,loop-4
- [Type-C]展开loop-1,loop-3
- [Type-D]展开loop-3,loop-4
Type-A
在Kernel, Input, Output中实现并行。但Kernel()通常很小(≤11×11),因此它不能提供足够的并行度,并且其他循环需要进一步展开。一个更具挑战性的问题是,在给定的CNN模型(例如AlexNet和ResNet )中,不同卷积层的内核大小可能会有很大差异,这可能导致工作负载不平衡和PE的利用率低下。为了解决这个问题,需要为具有不同内核大小的层配置不同的PE,这会增加控制的复杂性。
Type-B
在Type-A和Type-B中,不会展开Loop-3,这意味着无法重用权重。Type-B仅展开Loop-2和Loop-4,但是第一卷积层的通常很小(≤3×96)4,并且不能提供足够的并行度,这导致利用率和吞吐量较低。如果第一层受到计算限制,或者DRAM延迟不与计算重叠,那么吞吐量下降将影响整体性能,尤其是对于浅层CNN(例如AlexNet和NiN)而言。
Type-C
在Type-C中,Kernel窗口中的每一行都将完全展开(),并且Loop-3也将部分展开。通过这种方式,可以通过(15)中的由Loop-1和Loop-3引起的重叠来重用像素,并且还可以通过在(12)中展开Loop-3来实现权重重用。但是,Loop-4不会展开,并且无法实现进一步的像素重用。由展开Loop-1引起的PE效率问题也影响Type-C。
Type-D
在Type-D中,将Loop-3和Loop-4都展开,以便可以重用像素和权重。另外,在AlexNet,VGG和ResNet的所有卷积层中,(≥7×7×64)非常大,因此即使对于具有约3600个DSP Slice的最大FPGA,也可以实现并行级别。通过这种方式,PE的统一配置和结构可以应用于所有卷积层。
V. 具有特定设计变量的优化加速方案
1. 最小化延时
见公式(5)-(8)
为了充分利用PE,我们将变量P *设为所有卷积层的T *的公因子,并将T *设为N *的公因子,以充分利用外部存储。对于仅具有较小公因数的CNN模型,建议将和 (即余数)设置得尽可能小,以最大程度地减小因CNN模型的大小。
2. 最小化部分和存储
为了减少部分和的数量和移动,Loop-1和Loop-2都应尽早计算或尽可能展开。为了避免展开第IV节中讨论的Loop-1的缺点并最大化第III-3节中讨论的数据重用,我们决定展开Loop-3(或)和Loop-4()。这也意味着, 我们无法获得最小的部分和存储,如图9内的(9.1)。受的约束,部分和存储的第二个最小数由(9.2)实现图9中的(9.2)-(9.9)。为满足(9.2)的条件,我们首先对Loop-1和Loop-2进行串行计算,并确保对Loop-1和Loop-2的所需数据进行了缓存,即,$ Tkx = Nkx,Tky = Nky,Tif = Nif Pof×Pox×Poy $的部分和,可以将其保留在本地寄存器中,并且数据移动最少。
3. 最小化片上存储
通过展开Loop-3以重用权重(如公式(12)中所示)和展开Loop-4以便重用像素,如公式(14)中所示,可以最大程度地减少片上Buffer的访问次数。由于我们的部分和被保存在本地寄存器中,因此它们不会增加缓冲区访问和存储的开销。
4. 最小化片外访存
当我们首先计算Loop-1和Loop-2以减少部分和时,我们无法实现图10中(10.1)和(10.3)中所述的最小DRAM访问次数,其中一个卷积层的像素和权重均被未完全缓存。因此,我们只能通过为图10的(10.8)中的每一层的所有像素或所有权重分配足够的缓冲区大小来获得最小的DRAM访问。
然后,在最小化片上缓冲区大小的同时进行最小化DRAM访问的优化公式为
其中*#Tile_pxLand* #Tile_wtL分别表示输入像素的分块块数和层L的权重,而*#CONVs*是卷积层数。bits_BUF_px_wt是像素缓冲区大小(bits_BUF_px)和权重缓冲区大小(bits_BUF_wt)的总和,由下式给出:
像素缓冲区和权重缓冲区都必须足够大,以覆盖所有卷积层的一个切片块中的数据。表示为
其中words_pxL和words_wtL分别表示L层中一个分块的像素数和权重。这些以循环分块变量表示,如下所示:
其中words_pxL由输入和输出像素组成(20)中的分块数也由T∗变量确定
通过求解(20),我们可以找到变量的最佳配置,从而使DRAM访问和片上缓冲区的大小最小。但是,由于我们已经像第V-2节中那样设置了,因此我们只能通过调整和来实现次优解决方案,从而需要更大的缓冲区大小。如果可用的片上存储器足够,我们将设置为,以便可以缓冲整行,从而受益于DMA transaction。
最后,我们必须通过搜索和来求解(20),因为它具有非线性目标函数和带有整数变量的约束。由于VGG-16中的和由2×#CONVs = 26个变量组成,并且每个变量可以具有大约四个可选值,分别受整数和整数的约束,因此,$ To yTo f$配置约为,这成为一个巨大的求解空间。在ResNet-50 / ResNet152中,#CONV分别增加为53和155,这使得解决方案空间甚至更大,分别为和。因此,不可能列举所有候选解。
在本文中,我们建议根据经验为给定的利用CNN特性的片上存储容量找到令人满意的解决方案。 CNN通常在开始的几层中具有较大的像素数据量和较小的权重大小。当我们进入更深的层时,像素大小随着提取的特征而变小,权重大小随着更多的通道而变大。
图11中说明了这种趋势,其中的条形表示每个卷积层中的数据大小。**要受益于不同层中的数据分发属性,我们只需要使像素缓冲区完全覆盖最后几层,而权重缓冲区则完全覆盖开始的几层。然后,像素和权重都较大的中间层成为缓冲区大小的约束,我们只需要注意这些边界层,就可以大大缩小解决方案空间。**图11中的虚线是我们发现的最小缓冲区大小,同时保证了最少的DRAM访问,并且边界层由箭头指出。如果该缓冲区大小仍然无法装入FPGA片上存储器,则我们需要更改切片策略或减小缓冲区大小,但要付出更多DRAM访问的代价。
5. 优化循环设计变量
根据上述优化过程,我们提出了一种用于高性能和低通信量的CNN加速器的卷积加速方案,如图12所示。
循环展开:
对于所有卷积层,没有展开Loop1和Loop-2,这意味着和。根据(7)和(8),和为分别设置为特征图()和输出通道()的公因子,以充分利用乘法器。表II中列出了不同FPGA上不同CNN的,和的配置,这些配置在很大程度上受到可用计算资源的限制。通过将在所有卷积层上设置为常数,可以实现PE的统一结构和映射,从而降低体系结构的复杂性。
循环分块
对于循环展开,如第V-2节所述,如图12所示,设置,以便将Loop-1和Loop-2中使用的数据全部缓冲,设置使得DMA传输获益。 和的详细信息在第V-4节中已经描述过。
循环交换
我们首先按第V-B节所述依序计算Loop-1,然后计算Loop-2。最后,我们计算Loop-3和Loop-4,这两个循环的确切计算顺序不会对成本产生明显影响, 而是根据我们的和选择(这句话不知道理解的对不对)。
VI. 本文提出的CNN加速器
1. Data Bus From Buffer to PE (BUF2PE)
我们在图13中提出了BUF2PE数据总线,以使用FIFO实现数据流,以临时存储要由相邻寄存器阵列重用的像素。此方法类似于[22]中的行缓冲区设计,其中FIFO用于将多个特征行中的像素对齐到kernel窗口,以便可以在kernel窗口内采用并行,即展开Loop-1,而本文展开循环3以在一个特征图中进行并行计算。通过这种方式,简化了寄存器阵列内和寄存器阵列之间的布线,并且数据路由器可以遵循相同的模式进行卷积,具有不同的步幅和零填充,从而提高了加速器的灵活性。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FlkPJXEN-1592364305052)(https://i.loli.net/2020/06/17/iAv5g2pm8eOsSH1.png)]
BUF2PE数据总线的详细设计如图13所示。来自输入缓冲区的像素被加载到相应的寄存器中,如蓝色虚线框到蓝色实线框所示。然后,像素在周期0~5期间发送到PE或MAC单元,还发送到FIFO,等待相邻寄存器阵列重用。如图13中的紫色像素所示,除最右边的寄存器阵列外,在周期3开始从FIFO读取输入像素。同时,新像素从缓冲区馈入最右边的寄存器阵列。在本文中,由west zero padding引起的偏移是通过移动缓冲区和寄存器阵列之间的连接来处理的,而[15]必须通过填充偏移来更改输入缓冲区的一个地址内的存储模式,这会增加数据传输的复杂性从DRAM到缓冲区。
图14中以stride=1 和stride=2在特征图行级别上显示了粗粒度数据流。图14(a)中的数据流与图13相同,展示了8个周期之后更多的操作。
图14(b)给出了stride= 2, padding= 3的数据流, 它与stride= 1遵循相同的模式, 根据不同的stride和padding设置来调整缓冲区存储模式。由于north zero padding of 3将三行零添加到缓冲区。在stride= 2的情况下,每两行像素在个 buffer banks中连续分布。在从DRAM接收像素期间,这些调整由缓冲区写使能和地址信号处理。
由于padding和stride的设置不同, 每个数据流都需要各种BUF2PE数据总线,并且这组数据总线称为数据路由器。全局控制逻辑控制数据路由器内部不同BUF2PE总线之间的切换。
2. PE体系结构
根据建议的加速策略和数据流设计图15所示的卷积层的PE体系结构。它由$Pox×Poy×Pof $个PE组成,我们体系结构中的每个PE都是一个独立的MAC单元,由一个乘法器和一个累加器组成。由于Loop-1和Loop-2不会展开,因此不需要加法器树即可对乘法器输出求和。在每个MAC单元内消耗部分和,直到获得最终结果为止,
从输入像素缓冲区读取的像素由个MAC单元共享,滑动时重叠的像素也被数据路由器重用。从权重缓冲区读取的权重由 个MAC单元共享。所提出的体系结构通过参数化的Verilog代码实现,并且通过修改设计变量(例如),可以高度扩展到FPGA甚至ASIC中的不同CNN模型。
在Loop-1和Loop-2完成之后,部分总和需要加上如图1所示的偏置,以获得最终的输出像素。因此,每隔个周期,MAC单元会将部分和输出到加法器中,并加上偏置。
Conclusion
本文通过对循环优化技术进行数值表征,对卷积循环加速策略进行了深入分析。加速器目标和设计变量之间的关系进行了定量研究。提出了相应的新数据流和体系结构,以最大程度地减少数据通信并提高吞吐量。
更多内容欢迎关注我
博客:https://shawer.work/