作者:金牛梁浩_934 | 来源:互联网 | 2023-07-16 16:42
-
William J Dally 团队
- 文献一SCNN An Accelerator for Compresse d-sparse Convolutional Neural Networks1
- 文献二EIE Efficient Inference Engine on Compressed Deep Neural Network2
-
寒武纪团队
- 文献一DianNao A Small-Footprint High-Throughput Accelerator for Ubiquitous Machine-Learning3
- 文献二Cambricon-X An Accelerator for Sparse Neural Networks4
- 参考文献
William J. Dally 团队
Dally团队除了对神经网络处理器进行硬件优化,也提出了很多算法上的优化。包括
- 提出了一种训练方法,在训练过程中对神经网络进行剪枝,可以增加网络的稀疏性,(可以减少9x到13x的互联weight)。
- 对稀疏后的weight进行量化,这样数据就少了,可以使用LUT存储,在weight的量化过程中使用了K-means聚类算法。量化可以将weight的表示从32为降低为5位。
- 量化后的weight,以及其稀疏编码的index的分布是非均匀的,通过分析这种非均匀性,使用huffman这种压缩编码来进行存储,节省20-23%存储空间。
- 又提出在稀疏的时候,可以间隔着的稀疏,比如稀疏掉特定的一个滤波器,这样可以使稀疏后的数据更规整,利于加速。
文献一:SCNN: An Accelerator for Compresse d-sparse Convolutional Neural Networks1
作者:Angshuman Parashar,William J. Dally
摘要:
- 对卷积层进行优化
- 探索activation 和weight中的0来优化结构。在训练过程中通过将小于一定阈值的weight归零来增加weight矩阵的稀疏性。
- 将卷积运算分布到几个子PE中运算。
- activation和weight都使用稀疏编码来计算。
结构及优化分析
本文提高,CNN网络的稀疏性表现在两个方面:weight的稀疏性和activation的稀疏性。Weight的稀疏性可以通过一些剪枝算法来实现,比如韩松等人提出的剪枝算法。Activation的稀疏性来自于ReLU运算。
Weight和activation中的0不会对结果产生影响。因此通过利用CNN的稀疏性可以得到以下两个好处:1、压缩数据,通过使用压缩编码消除数据中的0,可以减小需要存储的数据量;2、消除不必要的计算,当weight和activation中有0时,我们既可以关闭计算单元来节省能耗,也可以直接跳过该运算,这样既节省能耗又节约时间。CNN硬件设计就需要充分利用这两个好处。
一个典型的CNN卷积层运算的数据结构和算法如上图所示,为一个7层嵌套的循环,其核心运算为滤波中的乘累加。硬件设计就是要对该循环进行并行加速。
首先假设数据的非稀疏的,先根据卷积运算的7层循环的特点来优化结构。由于weight和activation都很大,要进行分块处理。对于卷积运算,有两种循环方式:固定activation,循环weight;固定weight,循环activation。该文使用的前者,因此首先对weight进行分组,将k个通道(channel)的weight按照每组Kc个通道来分组,weight分组后的计算单元变为:
该文的结构SCNN由多个PE组成,因此对于以上的计算单元,又对activation进行分块。将WxH的activation平面,按照Wt × Ht的格子进行分割,每个PE计算的activation数量为C ×Wt × Ht。weight通过广播的方式同时广播到每个PE,每个PE完成各自部分的乘累加运算。
在activation分割成格子的时候,会出现data halo问题,即在未分割的时候,卷积是在整个WxH平面上进行的,分割之后,卷积在在小格子的边界附近就无法得到完整结果,因为有一部分数据是在另一个PE里面。解决的办法有两种:1、在每个PE的输入的activation比Wt × Ht略大一些,通过activation来解决data halo问题;2、在每个PE计算完的累加缓存做的比Kc × Wt × Ht大一些,多出来的部分存储着不完全的累加值,然后通过相邻计算单元间的通信再得到完整结果。两种方案资源消耗相当,该论文选择的是第二种方案。
然后在每个PE里面要计算通过一个二维的乘法矩阵单元计算,F个weight和I个activation依次相乘,得到FxI个结果。然后这些结果在一个累加单元里累加,得到最终的输出结果。
通过以上几步,得到并行化后的对于非稀疏CNN卷积的优化算法,伪代码如下。
将上述针对非稀疏CNN卷积的分析过渡到稀疏CNN,有两方面的修改。
1、首先,weight和activation都是稀疏表示的,因此输入输出的地址都要通过index计算。为了地址计算的方便,稀疏表示的weight和activation的压缩也是分组进行的,每一个Kc × R × S块中的weight压缩成一组,每一个Wt × Ht区域内的activation压缩成一组。在处理的时候,数据也是按这样的组进行的。
2、稀疏表示后,输出矩阵并不像上图一样是规整的Kc ×Wt × Ht矩阵,也是稀疏的(有些地方没有0)。因此,累加单元不能直接对输出结果进行累加,这里将乘法矩阵输出的IxF个数据,通过一个crossbar输入到一个加法累加buffer中,通过crossbar使属于同一个输出位置的乘法结果输出到同一个累加buffer中,每个累加buffer最后将结果累加得到最后的输出。
以下是最终的系统结构图。
简评
优点:
1、weight、activation稀疏表示;
2、探索卷积运算的多次循环的可并行性,通过多PE结构进行并行计算;
3、计算后的结果如果能作为下一次的activation,则保存在本地PE,避免了重复存取。Tips,这里感觉有个潜在不足,就是每一层的输出其实矩阵是和前一层不一样的,因此,这里的activation应该是所有PE一起的一个整体的调整,可能没有直接存在PE本地那么简单,可以仔细研究一下。
不足:
1、对于卷积层的计算优化的很好了,但是对于全连接层优化有限。
文献二:EIE: Efficient Inference Engine on Compressed Deep Neural Network2
作者:Han Song,William J. Dally
摘要:
- 对FC层进行优化(全连接层没有卷积层那样的重复,矩阵带宽最大)
- 对weight、activation进行稀疏表示
- weight 有限精度 4bit
- 将weight按行分配到每一个PE中,计算时将activation广播到所有PE,
这样分配可以使每个PE计算后就直接得到相应位置的输出。
结构优化及分析
对于卷积层的加速已经有很多人做,但是对于RNN和LSTMs来说,存在着大量的全连接层(FC),RNN广泛应用于图像捕捉和自然语言识别等领域。本文对FC层进行加速。FC层的特点是所有的输出和所有的输入都有连接,在较大的层里,内存读写就是主要瓶颈。对此本文做了以下优化:
- 稀疏表示activation和weight,使其可以片上SRAM存储;
- 共享weight,即每个PE里weight固定,然后和不同的输入activation运算,不用反复读取weight
- weight使用查找表存储稀疏后的weight值,通过4bit的index索引
- 对于系数矩阵运算,使用分布式存储,分布式运算的方法来在多个PE中并行计算。该方法可以实现各PE的负载均衡。
稀疏表示的weight存储结构如图所示,可以看到,weight是按列存储的,且一个PE核对应的weight存在对应PE里。如对于PE0,存储一次是第一列的绿色非零weight,第二列的非零weight。这样就可以每进来一个activation都可以把和他相关的weight运算都算完。按列存储的好处是可以更好的处理activation的稀疏性,只要将非零的activation乘以对应列中非零weight即可。
在运算的时候,activation被广播到所有PE,与每个PE对应列处的非零weight进行计算。
这样计算的话,每个PE的计算量可能不同,进而导致load imbalance。为了解决这一问题,在activation输入每个PE后存储在一个队列里面,如果有一个PE的activation队列满了,则停止输入activation的广播。(tips,这种做有个缺点是,当有一个PE计算量大的时候,其他PE的队列已经空了,这时候就要停下来等他,有没有可能把负载过重的PE工作分配到别处?或者在训练的时候就保证weight的均衡性)。
PE计算完后,通过ReLU会出现0,也就是说对于下一层计算的activation也需要先稀疏表示,这个工作通过LNZD模块完成。LNZD的连接是四叉树型结构(如下图左边),每个LNZD接收4个PE的值,稀疏表示后再依次送到上一级的LNZD节点。LNZD这样的树型结构可以保证增加节点的时候线宽可以保持一致(tips,方便扩展)。
该加速器整体结构如下图所示
简评
优点:
1、稀疏矩阵的乘法中,weight按列存取,多核计算更方便;
2、PE的输入activation使用队列缓存,可以进行负载均衡控制;
3、对于输出activation进行稀疏表示的时候,使用了一个树型结构,方便结构的扩展。
不足:
1、对于全连接层的计算优化的很好了,但是对于卷积层几乎没有优化
2、文中自己提高一个不足,weight按行分配到PE中,activation需要广播到每个PE中,这样对于相应列没有计算的PE也需要接受activation,并做判断。
但是如果列存储,每个PE计算后的结果,还需要最后有一个单元来进行汇总。也可以将weight分块,就可以结合以上两种方式的优点,但是结构就会很复杂。因此这个问题上有个取舍,或许还有更好的方案。
寒武纪团队
摘要
- 没有使用多个PE核的结构
- 寒武纪注重数据并行化方面的优化,加速器使用一个三级的流水结构:乘,加,sigmoid。
- 可以支持多种神经网络结构 (MLP, CNN, RNN, LSTM, Autoencoder, Sparse Autoencoder, Boltzmann machines (BM), Restricted boltzmann machine (RBM), Self-organizing maps (SOM), Hopfield neural network (HNN))。
结构优化及分析
改论文分析了CNN和DNN等深度神经网络,提取出三类关键算法层:分类层(classifier layer,优点类似全连接层),卷积层,pooling layer。对应的通用算法有:乘法,累加,以及sigmoid等特殊运算。根据对这些运算分析,提出了一个三级流水的结构,分别进行乘法,累加,sigmoid运算。
对于分类层,需要用到乘法、累加、sigmoid都会用到;对于卷积层,也是所有级都用到,最后一级的sigmoid也可以变为其他核函数;对于pooling layer,没有乘法,第三级的运算也不是sigmoid,可以是求平均或者求最大值。
在该结构中,为了对大型网络进行运算,使用了输入输出队列来保持activation和weight。输入数据根据队列的大小分块输入。输入activation有时候需要复用,因此activation对应的输入队列NBin被设计出circular buffer。因为输入是按块输入的,因此输出的累加值不是最终结果,为了不重复存取,第二级(NFU-2)有一个delicated register来存储累加值。
简评
感觉整体上是一个中规中矩的处理器设计思路:算法抽象,提取kernel,设计处理器。三级结构比较直观。不足是感觉整个结构是直接的算法映射,由于设计的比较通用,所以可能针对特定算法的结构优化就少一些。
这个结构追求的通用性更强一些,不太适合短时间跟进
文献二:Cambricon-X: An Accelerator for Sparse Neural Networks4
摘要
在DianNao基础上加入稀疏编码模块,只选择不为零的activation进行计算;
该结构对classifier layer加速明显,但是对conventional layer加速有限。
结构优化及分析
该结构是在DianNao结构基础上的改进,添加了对activation和weight稀疏的支持。
可以看到,主要的改进是在输入/输出缓存和运算单元之间,加了一个buffer controller。Buffer controller里有两个单元,BCFU用来存储根据IM选择的神经元。IM(indexing module)是稀疏表示的关键,用来根据索引来确定需要计算的神经元,并将对应的数据分配给各个PE计算。文中给出了其根据稀疏表示的index寻址的结构(结构可以借鉴)。
简评
该结构对输入数据的稀疏性进行了处理,但是对于输出后新产生的稀疏数据没有进行处理。
参考文献