论文笔记:An Efficient Hardware Accelerator for Structured Sparse Convolutional Neural Networks on FPGAs
An Efficient Hardware Accelerator for Structured Sparse Convolutional Neural Networks on FPGAs
Abstract
深度卷积神经网络(CNN)在广泛的应用中都实现了最先进的性能。但是,复杂的人工智能(AI)任务广泛需要更复杂的更深的CNN模型,这些模型通常对算力的要求极高。尽管最近在网络压缩方面的研究进展(例如剪枝)已经显著减轻了硬件设备的计算负载,但是由于剪枝引起的不规则性,仍然无法阻止现有的加速器充分利用稀疏性的好处。另一方面,现场可编程门阵列(FPGA)是一个前景广阔的CNN推理加速硬件平台。但是,大多数现有的FPGA加速器都集中在密集的CNN上,无法解决不规则性问题。在本文中,我们提出了一种稀疏数据流,以跳过处理权重为零的乘加累加(MAC)的周期,并利用数据统计信息通过零门控来最大程度地减少能量,以避免不必要的计算。我们提出的稀疏数据流满足低带宽需求和高数据共享。然后,我们设计了一个包含矢量发生器模块(VGM)的FPGA加速器,该模块可以根据所提出的数据流匹配稀疏权重和输入**之间的索引。实验结果表明,对于Xilinx ZCU102上的AlexNet,VGG-16和ResNet-50,我们的实现可以分别实现987-,46-和57-image/ s的性能,分别提供1.5×–6.7×的加速,以及相比之前的CNN FPGA加速器2.0x-6.0x的能效提升。
Introduction
卷积神经网络(CNN),例如AlexNet [4],VGG-16 [5]和ResNet [6],在各个领域[1] – [3]中获得的显着的性能提高,是以庞大的计算和巨量的数据作为代价,这对加速器体系结构设计中的片上存储和片外带宽都提出了挑战。尽管CNN训练和推理中的大多数操作都可以转换为矩阵乘法操作,并可以通过现代图形处理单元(GPU)进行加速,但是在GPU上部署CNN仍然会消耗大量功率和面积。定制的加速器已被视为有前途的替代方案,在考虑性能要求和能量限制时更为灵活[7] – [18]。
最近,CNN剪枝技术已被证明是减少这些模型的计算和内存需求的有效解决方案[19],[20]。例如,Han等指出,剪枝可以使数据量减少十倍以上,而精度损失可忽略不计。另一方面,已经提出了包括量化和熵编码的权重编码,以进一步减小每个权重的位宽,例如,AlexNet的权重为4位[20]。非结构化剪枝技术,例如深压缩[20],具有负载不平衡和高不规则性的缺点。因此,提出了结构化剪枝技术[21]-[24],它们在压缩率稍低的情况下对硬件更友好。
但是,稀疏性导致的不规则性会阻止加速器充分利用剪枝带来的计算和数据的减少。密集模型的现场可编程门阵列(FPGA)上令人兴奋的体系结构对于稀疏的CNN模型而言效率不高,因为剪枝了大量权重,因此大多数乘法运算涉及零操作数,从而导致较低的硬件效率[9],[25]- [29] 。近年来,FPGA上的稀疏架构的研究引发了广泛的兴趣[30],[31]。 Han等设计了使用矩阵矢量乘法运算的全连接(FC)层。实际上,CNN的主要运算符是卷积运算。尽管空间卷积可以转换为矩阵向量乘法,但这将导致较大的内存占用,因为在将输入特征图展平为向量时必须将其复制多次。 Lu等提出了一种利用元素矩阵乘法作为关键操作的数据流。但是,由于每个处理引擎(PE)的负载不平衡,因此该设计的计算效率较低。由于此加速器需要大量的查找表(LUT)来缓冲非零权重的输入**,因此性能受FPGA上LUT数量的限制,这导致资源利用效率低下。
为了为稀疏的CNN模型设计高效的FPGA加速器,必须解决以下挑战:
首先,每个输出**都通过密集卷积(CONV)层中的滑动窗口(卷积核)连接到多个输入**。剪枝后,连接变得不规则。同时,稀疏权重以压缩格式进行编码,这导致了额外的坐标计算,以重建连接或定位输出。因此,设计一个数据流来解决不规则性是一个挑战,而它却有效地利用了数据和计算量,并保持了FPGA的高度并行性。
其次,FPGA只能提供有限的片上存储器和片外带宽。尽管稀疏的CNN具有明显的数据缩减功能,但是很难将所有权重保存到复杂的CNN(例如VGG-16)的片上存储器中。此外,不同的CNN模型具有不同的大小,从而导致操作数量的高度可变性。用于CNN的刚性加速器架构可能无法针对每种CNN模型充分利用FPGA有限的资源。
为了应对这两个挑战,我们仅关注结构化剪枝以减少稀疏权重的不规则性。在此基础上,提出了稀疏数据流以解决稀疏权重的剩余不规则性。利用建议的数据流,我们不需要额外的坐标计算即可重建连接或定位输出。此外,如果输入**为零,我们通过零门控制将能量降至最低,以避免不必要的计算。
总之,我们做出了以下贡献:1)我们提出了一种稀疏数据流,以跳过权重为零的乘加累加(MAC)的处理周期,并通过零门控来最小化能量,以进一步避免不必要的计算; 2)我们提出了一个向量生成器模块(VGM),可以为稀疏的CNN重新使用并生成必要的输入**; 3)我们对加速器架构和循环切片进行代码签名,以通过切分输入功能图来最大程度地匹配FPGA上块随机存取存储器(BRAM)的容量,从而最大程度地减少片外存储器访问并最大化性能。
实验表明,所建议的加速器在Xilinx ZCU102上分别可将AlexNet,VGG-16和ResNet-50的性能提高到987-,46-和57-image / s,可提供1.5×–6.7×的加速比,能源效率是之前的CNN FPGA加速器的2.0×–6.0倍。
Background
CNN由多种类型的层组成,包括卷积层,池化层和FC层。通过这些层,对输入进行处理和传播,从而进行分类或识别。卷积操作使用R×R窗口在输入特征图中滑动以提取特征。在每个位置,窗口内的输入**都将乘以相应的权重,并对乘积进行累加以计算输出**的部分总和。请注意,将累加不同输入通道中的部分和以计算输出**。
A.网络剪枝
CNN在各种应用程序[1] – [3],[32],[33]中取得了显著成功,但要付出大量的计算成本。权重剪枝方法已被证明是一种有效的解决方案,可以减少这些模型的计算和存储负担,并且准确性损失不明显[19] – [24]。结构化稀疏性学习(SSL)[34]建议在过滤器,通道,过滤器形状等级别学习结构化稀疏性。图1说明了CNN的CONV层上的三种结构化剪枝方案:卷积核剪枝,通道剪枝和形状剪枝,它们删除了整个过滤器,整个通道和所有神经元在每个过滤器中的同一位置一层。最近,基于强大的乘法器交替方向方法(ADMM)的优化工具,开发了系统的解决方案框架[24]。此外,AutoCompress [35]采用基于ADMM的最新结构化权重剪枝作为核心算法,并提出了一种自动结构化剪枝框架。 Cambricon-S [23]在CONV和FC层上都应用粗粒度剪枝(一种形状剪枝)来剪枝权重。
与非结构化剪枝技术相比,结构化剪枝技术更常规且对硬件更友好,但代价是其稀疏性略高。表I显示了深度压缩[20]和粗粒度剪枝[23]的稀疏性和准确性比较。深度压缩和粗粒度剪枝之间的稀疏性差异几乎可以忽略不计。但是,与深压缩相比,粗粒剪枝可以实现非常有希望的压缩率。
B.循环操作
在典型的CNN中,卷积层在推理过程中约占计算量的90%。卷积层可以通过六个参数来表征:F-输出特征图(输出通道)的数量; C-输入特征图的数量(输入通道); U-输出特征图的高度; V -输出特征图的宽度; R-卷积核大小; S-步幅大小,如图2所示。可以在深度嵌套的循环中描述计算,如算法1所示。与特征图相关的循环f和c分别为输出和输入通道建立索引。**相关的循环u和v为特征图的每次**编制索引。最后,权重相关循环kh和kw索引每个卷积核的权重。显然,卷积运算在通道,**和权重级别上显示出很高的并行度。
为了获得高性能,将上述深度嵌套循环展开并映射到并行硬件。这涉及循环切片和循环交换策略[36]。循环切片将循环切片的所有输入数据保留在芯片上,以减少对外部存储器的访问。当新图块的操作开始时,发生外部存储器访问。此外,一部分数据可以在相邻图块之间在时间上重用。循环交换策略决定了循环块的顺序。循环切片和循环交换策略都决定了硬件的数据流。
C.加速按卷积核和按通道剪枝的CNN
可以通过优化内存读取和循环控制,在硬件上加速按通道的稀疏性和按过滤器的稀疏性。图3说明了逐通道硬件加速的概念。在此示例中,剪枝了第i层中每个卷积核的第三通道,因此(算法1中)第二个循环的上限减小为(C-1)。因此,如果跳过输入特征图中第三通道的存储器读数,则可以跳过相应的计算。图4是过滤器硬件加速的示例。如果剪枝了第i层中的第二个过滤器,则第一个循环的上限(在算法1中)将减小为(F-1)。如果稀疏滤波器已压缩为密集格式,则可以跳过第i层中的相应计算。同时,随后的第i + 1层变为按通道剪枝,如前所述,可以跳过相应的计算。
因此,可以在密集加速器上加速按过滤和按通道剪枝的计算,而无需添加额外的硬件电路,这可以通过优化**或权重和循环控制的内存读取来实现。但是,无法通过跳过读取通道级别的**或形状剪枝中的权重来实现加速。需要额外的硬件电路来决定哪些**部分需要加载到PE中或定位输出**。为此,我们在此设计中提出了稀疏数据流和一组体系结构优化技术。
Sparsewise Dataflow
FPGA [9],[25],[37]上有密集的CNN数据流。但是,这些数据流无法利用稀疏CNN的好处,因为大多数乘法运算涉及零权重,这将不会有助于相应的输出特征图。因此,跳过具有零权重的MAC的处理周期非常重要。
最近,在ASIC平台上设计稀疏CNN的数据流引起了研究界的关注。但是,由于ASIC和FPGA之间的体系结构差异,这些数据流对于FPGA平台而言效率不高。例如,SCNN体系结构应用输入平稳数据流,其中内部计算是笛卡尔积。在SCNN架构中,有N个PE,每个PE包含一个I×D乘法器阵列。因此,它同时需要N×I个输入**和N×D个权重才能进行计算。尽管此数据流在时间上重新使用了输入**,但仍需要在每个周期中更新N×D权重。此外,此方法首先需要进行大量的坐标计算才能定位输出**。然后,使用笛卡尔乘积,此数据流返回多个需要保存的部分和。 Cambricon-S [23]应用输出平稳数据流,其中内部计算是矢量点积。 CambriconS实施集中式索引模块以选择输入**,并且仅将选择的**和索引传输到PE,而无需额外的坐标计算。但是,此数据流仅通过空间共享输入**来在通道维度上执行并行计算,因此需要M个输入**和N×M权重进行计算,这将导致FPGA的并行性差。
我们提出了一种稀疏数据流来加速FPGA上的CNN(请参见算法2)。
对于具有输入特征图Ifamp
(C,H,W)和卷积核Kernel
(F,C,R,R)的卷积层,我们在每次访问时从
T
o
c
T_{oc}
Toc个相邻卷积核中选择并提取
T
o
c
T{oc}
Toc个非零权重,组成为一个向量。同样,我们还获取输入特征图的每一行中的
T
o
m
T_{om}
Tom个**并组成一个向量。同时,我们在PE阵列上计算
T
o
c
T_{oc}
Toc元素向量乘法。经过形状结构化修剪后,不同卷积核中非零权重的坐标将统一。因此,每个元素向量乘法都涉及一个权重和一个共享向量(包含
T
o
m
T_{om}
Tom个**)。例如,在步骤1中,权重向量为
[
W
0
,
0
0
,
0
,
.
.
.
,
W
0
,
0
T
o
c
,
0
]
[W_{0,0}^{0,0}, ..., W_{0,0}^{T_{oc},0}]
[W0,00,0,...,W0,0Toc,0],并且输入向量是
[
X
0
,
0
0
,
.
.
.
X
0
,
T
o
m
0
]
[X_{0,0}^0, ...X_{0,T_{om}}^0]
[X0,00,...X0,Tom0]。在步骤2中,我们获取权重向量
[
W
0
,
1
0
,
0
,
.
.
.
W
0
,
1
T
o
c
,
0
]
[W_{0,1}^{0,0},...W_{0,1}^{T_{oc},0}]
[W0,10,0,...W0,1Toc,0]和输入向量
[
X
0
,
j
u
m
p
0
,
.
.
.
X
0
,
T
o
m
+
j
u
m
p
0
]
[X^0_{0,jump},...X^0_{0,T_{om}+jump}]
[X0,jump0,...X0,Tom+jump0]用于下一次计算,并在并行模式下计算
T
o
c
T_{oc}
Toc个元素矢量乘法。变量jump
等于卷积核同一行中相邻非零权重之间的零个数。
产生相邻输出的卷积窗口共享部分输入**。因此,从输入特征图的同一行提取的两个连续的输入矢量涉及部分共享的数据。我们添加了专用的VGM(将在第IV节中介绍)来更新输入寄存器以重用数据。我们在图5中描述卷积运算执行模式。使用图5中的模式,四个PE计算四个相邻的输出**,并跳过具有零权重的MAC处理周期。
对于具有输入向量I_vector(C,1)和权重矩阵W(F,C)的FC层,权重缓冲区(WB)在每次访问时从矩阵W的相邻行传递包含 T o m T_{om} Tom个非零权重的向量(参见图6)。输入寄存器仅提供一次**。
特别是在1×1 CONV层中,按形状修剪相当于按通道修剪,因为每个通道中只有一个**。因此,用于1×1 CONV层的数据流(请参阅算法3)与算法2中描述的完全不同。因此,加速1×1 CONV层有两个步骤:步骤1-压缩卷积核以获得步骤索引数组index[]和offset;第2步-将第三个循环(在算法3中)的上限设置为Offset并根据索引更新activation_read_address
。
此数据流需要一组缓冲区来保存卷积运算产生的部分和。考虑具有输出特征图Ofamp
(F,U,V)的卷积层,我们应用了N×M PE数组。使
T
o
c
=
N
T_{oc} = N
Toc=N而
T
o
m
=
M
T_{om} = M
Tom=M可以防止部分和被保存到DRAM或从DRAM恢复。部分和(PSB)的深度至少应为
U
∗
V
M
\frac {U*V}M
MU∗V。但是,某些CNN(例如VGG-16)在前两层中包含相当大的U*V
乘积。因此,我们将输入特征图划分为
H
H
t
\frac H H_t
HHt切片,其中
H
t
=
(
U
t
−
1
)
×
S
t
r
i
d
e
+
R
=
(
M
∗
S
l
i
c
e
B
R
A
M
V
−
1
)
×
S
t
r
i
d
e
+
R
(
1
)
H_t =(U_t − 1)×Stride+ R = (\frac {M*Slice_{BRAM}} V − 1)×Stride+R \ \ \ \ \ \ \ (1)
Ht=(Ut−1)×Stride+R=(VM∗SliceBRAM−1)×Stride+R (1)
参数SliceBRAM
表示FPGA上一块BRAM的容量。相邻图块共享R-Stride
行,因为卷积操作的滑动窗口性质在图块边缘引入了数据依赖性。当输出特征图的宽度V<M
时,为了提高效率,我们将
[
M
V
]
∗
V
[\frac M V]*V
[VM]∗V tile映射到一个处理单元(PU),因为每个PE计算一个输出**。否则,我们将1×M tile映射到一个PU,如图7所示。PE阵列由N个Pu组成,每个PU在同一行中由M个PE组成。输入**在PU之间共享。不同的PU计算来自不同输出通道的输出**。
通过在空间上共享输入**和权重,并在时间上重用部分输入**,我们将带宽需求降低为N×B + M×A。因此,我们提出的加速器的带宽需求比Cambricon-S(M ×A + N×M×B)
和SCNN(N×D×B)
小很多,其中A和B分别代表**值和权重的宽度。
Architecture of Sparsewise Accelerator
在本节中,我们将介绍加速器的详细架构,以解决形状修剪后的CNN的剩余不规则性。
概述:图8描绘了我们提出的加速器的整体框图。按照提出的数据流,我们设计了一个VGM来解决共享索引的稀疏性。我们设计了一个具有多个PE的PU,以并行计算相邻的输出**。多个PU组成一个数组,以并行计算跨输出通道的多个输出**。存储模块由两个**缓冲区(ABin和ABout),一个权重索引缓冲区(WIB),N个WB和N×M个PSB组成。主控制器将指令和权重索引解码为所有其他模块的详细控制信号。
A.稀疏寻址
该加速器旨在利用结构化的稀疏性来提高性能并降低能耗。在我们的加速器中,稀疏性由VGM和PU一起处理。 VGM从ABin接收输入**,从WIB解码权重索引,然后生成选定的**,并广播到所有PU。同时,这些输入**将被缓存以供VGM中的下一个选择使用,因为当内核在输入特征图上滑动时会有重叠。每个PU从主控制器接收读取的权重地址,并按照建议的数据流中描述的原理读出所需的权重,从而避免不必要的计算。 1)索引:在详细介绍VGM和PU之前,我们清楚地解释了如何存储和索引稀疏权重。我们使用压缩稀疏行(CSR)格式存储因形状修剪而产生的稀疏权重,该格式仅需要2a + R×C + C个数字,其中a是非零权重的数量,R是行数,C是输入通道数。尽管在结构化修剪后不同的滤镜可以共享相同的索引,但是每个3-D滤镜仍可以平铺在不规则的稀疏矩阵中。为了进一步压缩,我们存储步骤索引而不是绝对位置。如图9所示,我们将步长索引和R_pointer都编码为4位,将偏移量编码为16位,如图9所示。4位索引在卷积层中足够大。但是,FC层的情况有所不同。当我们需要一个比边界大的索引时,我们将填充填充零以防止溢出。关于图10中的示例,当步长索引超过最大的4位无符号数时,我们填充填充零。
- VGM:VGM模块通过选择所需的输入**来处理稀疏性,并将所选的输入**转移到所有PU(请参见图11)。
我们设计了由多个PU共享的中央VGM,以更有效地处理结构化稀疏性中的共享索引。例如,首先,当索引为“ 1”时,寄存器REG0中的**将向左移动A位(最左边的A位,其中A表示**的宽度),并将广播带有索引(REG0[0], REG0[Stride], . . . , REG0[(M − 1) × Stride])的数据到所有的PU。在周期1中,当索引为“ 0”时,寄存器REG0中的**将进一步移位A位。
PU使用先前选择的输入**来执行MAC,并在此周期中缓存VGM选择的**。在周期2中,内核kh的行数(请参见算法2)增加。因此,REG0从REG1重新加载**,并根据新的权重指数进行数据移位。 REG0和REG1的深度均设置为(M − 1)×步幅+R。为了利用**选择和内存访问之间的重叠,在REG0最终从REG1重新加载**之后,将更新REG1中的**。由于PU由于形状修剪而共享相同的权重索引,因此用于选择**的模块(VGM)被所有PU共享,从而减少了索引模块的开销和VGM与PU之间的带宽需求。
3)PU:PU处理CNN中的所有操作。每个PU包含M个零值鉴别符,M个同质PE,M个同质PSB,一个WB,合并,归一化和**模块(请参见图12)。权重可以分别存储在PU中,因为来自不同通道的输出**涉及独立的内核。选定的**首先流入一个零值鉴别器,然后如果不等于零,则将在PE中使用。同时,鉴别器产生使能信号以控制PE的时钟门控。当所选**等于零时,相应的PE被时钟门控。为了最大程度地减少数据通信,由PE产生的部分和将保存在PE旁边的本地PSB中。在完成输出**的整个计算之前,最终的部分总和将被传输到**和合并模块。由于在FC层中既没有空间共享也没有时间上的权重重用,因此需要相当大的输入带宽。尽管所有PU都可以在FC层中处于活动状态,但在FPGA平台上无法满足所需的片外存储器带宽。因此,当FC层中的M足够大时,我们仅使一个PU处于活动状态。
B.优化PE量化
模型压缩的最常用方法之一是量化权重和**。低位**和权重需要较小的带宽,如果加速器是一种计算受限的设计,则这有利于提高吞吐量[15]。但是,建议的设计受BRAM限制。直接增加PE阵列的大小将导致在FPGA上实现失败,因为所需的BRAM数量很容易超过可用数量。因此,我们维护**的数据路径并优化PE的结构。例如,**和权重被量化为8位。我们将两个选定的8位**分配到一个PE中。由于建议的数据流,两个**分别在两个数字信号处理(DSP)片中以相同的权重相乘。然后,可以将部分和连接起来并存储在缓冲区中。
C.存储
由于在加速器中处理的数据具有不同的行为,因此我们将存储分为五个部分:ABin,ABout,WIB,N WB和N×M PSB。对于ABin和ABout,我们分别将宽度设置为16×(M − 1 + R)位和16×M位,以便为VGM提供(M − 1 + R)输入**并获取M个输出**从PU每次访问。受益于建议的数据流,N个PU共享相同的输入**,并且我们逐行读取输入**并产生输出**。因此,我们为ABin和ABout设置了较小的深度。对于每个PU中的WB,我们使用双端口ram,为此,我们将一个端口的读取宽度选择为16位,而另一个端口的读取宽度选择为16×M位。特别地,两个端口的写入宽度均为16×M位。在卷积层中,将仅读取一个权重并将其广播给所有PE,而在FC层中,将提取M个权重并将其传输到相应的PE。对于WIB,我们将宽度选择为16位,因为我们使用CSR格式,在此我们分别将16位,4位和4位部署为Offset,Index和R_pointer。因此,Index和R_pointer被存储为与4位对齐。对于压缩权重指数的三个组成部分,我们将WIB分为三个部分。对于PSB,我们将宽度设置为32位。我们将部分和存储在PSB中并缓存输出**,因为ABout依次从PU提取输出**。我们将每个PSB映射到一个BRAM。如果我们将每个PSB映射到两个或多个BRAM,则片上存储器资源将很容易成为可用峰值性能的瓶颈,从而导致吞吐量下降。五个缓冲区的大小决定了整体性能和能耗。例如,PSB的大小决定了瓦片的数量。小尺寸的PSB需要大量的图块,从而导致昂贵的片外存储器访问,而大尺寸的PSB则导致CNN中小层的不可扩展性。因此,我们通常分别为ABin,ABout,WIB,WB和PSB分别部署2 KB,2 KB,4 KB,512 B和2 KB。这些缓冲区的配置可以根据CNN进行调整。