Drift: Leveraging Distribution-based Dynamic Precision Quantization for Efficient Deep Neural Network Acceleration【DAC‘24】
介绍了一种新的DNN加速方法,Drift,通过基于数据分布的动态精度量化来提高深度学习模型的运行效率
一、文章背景
1. 背景
随着DNN模型变得越来越庞大(两年内增长了240倍),现有的静态量化方法不足以充分利用模型中的稀疏性和冗余性,尤其是对于越来越大的模型(例如LLMs)。
2. 动机
现有的静态量化方法固定了数据的精度(如权重和激活值),但DNN中的数据通常是动态的,各个区域的数据分布特性差异较大。因此,使用静态量化无法充分利用这些差异。例如,在图像分类任务中,物体的像素比背景像素更重要。这样的动态性无法通过静态量化来充分体现。
图1中的三张子图展示了子张量(张量的一部分,即从一个更大的张量中提取出来的一个较小的矩形或立方区域)在DNN中的动态性和分布情况:
- (a) Sub-tensor profiling in ViT:图像Transformer模型中的子张量分析,展示了子张量的最大值和平均值的分布,表明不同子张量之间的差异很大。
- (b) Sub-tensor profiling in BERT:在BERT模型中的子张量分析,展示了类似的现象,即不同子张量的最大值和平均值之间的差异。
- (c) Sub-tensor distribution in BERT:显示了BERT模型中的子张量分布,表明这些子张量的分布符合拉普拉斯分布。
3. 动态量化
一些研究已经开始探索动态量化,这种方法根据数据的动态性调整计算的精度。例如,DRQ是一种根据激活张量的不同区域动态选择4位或8位精度的算法,而DTQAtten则为自然语言处理模型中的每个token选择不同的精度。然而,现有的动态量化算法存在两个主要问题:
- 现有算法通常针对特定的场景设计,无法泛化到其他类型的DNN模型。例如,直接将DRQ应用于BERT模型会导致超过12%的精度下降。
- 现有的支持静态量化的加速器无法高效支持动态精度的计算。
4. Drift动态量化算法
为了解决上述问题,文提出动态精度量化算法,可以动态地选择不同的数据精度。具体来说,它会根据低精度格式的“表示能力”来选择合适的精度设置,同时保持计算精度不损失。
核心思想
- 动态选择子张量(如激活张量中的部分区域)的精度。通过分析子张量的数值分布,算法能够判断哪些区域可以使用低精度进行计算,哪些区域需要更高的精度。
- 这种方法可以利用现有的硬件资源,不需要额外的计算或芯片面积的开销。
5. Drift硬件架构
为了支持该算法,研究设计了一个新的加速器架构
- Drift可以将不同精度的计算分配到不同的systolic arrays中,避免因动态精度计算带来的数据流阻塞问题。
- Drift的在线调度策略可以在运行时动态平衡不同精度计算的资源分配。
动态精度计算带来的数据流阻塞问题:
在流水线中:
不同精度的数据流处理时间不同:例如,4位精度的数据处理比8位精度的数据快得多。如果同一个硬件单元需要同时处理不同精度的数据,处理8位精度数据时会占用更多的资源和时间,这会导致处理4位数据的过程等待,从而产生阻塞。硬件资源配置不匹配:很多现有的硬件加速器在设计时是针对固定精度量化进行优化的,比如每个PE可能预先设定为处理8位或更高精度的数据。当引入动态精度时,硬件必须频繁地调整以适应不同精度。
6. 实验结果
通过实验验证,Drift算法在各种DNN模型(包括CNN、Transformer、BERT模型)上表现出色:
- 速度:Drift加速器比现有的精度灵活加速器(如BitFusion)快了2.85倍。
- 能耗:Drift节省了3.12倍的能量。
- 准确性:Drift在保持模型准确性的同时,能极大提高低精度计算的比例。
二、前置知识及动机
1. 动态精度量化简介
动态精度量化是一种在运行时根据数据的动态特性选择不同精度的量化方式,以降低计算成本。例如,对重要的区域(如模型中的关键部分或激活值)使用高精度(如8位),而对次要区域(如稀疏区域或不重要的数据)使用低精度(如4位)。这种方法可以大大减少计算资源的使用。
2. 子张量的动态性
DNN模型中的数据通常以张量形式存储,一个子张量是张量的一个子集。例如:
- 在视觉Transformer(ViT)模型中,子张量可以是激活张量中的一个图像块(patch)。
- 在BERT模型中,子张量可以是激活张量中的一个token(词元)。
研究表明,不同的子张量具有显著不同的数值特性。例如,某些子张量的数值变化较大,其他子张量可能变化较小,因此为所有子张量使用相同精度并不高效。子张量的动态性提供了减少精度的机会,尤其是在不重要的区域可以使用较低精度。
3. 动态精度量化的挑战
数据流阻塞问题:动态精度量化需要在运行时根据数据的实际情况决定精度。然而,现有的加速器由于硬件架构的限制,难以在不同精度之间快速切换。特别是在一个计算单元中处理4位和8位精度的数据时,处理高精度数据的计算需要多次循环,导致其他部分的计算等待,最终引发数据流阻塞。
精度阻塞问题,上述已说明。
4. 现有方案的局限性
动态精度量化的选择标准在不同类型的DNN模型之间不可通用。例如,针对图像分类的动态量化方法不适用于自然语言处理模型中的BERT。
现有的精度灵活加速器(如BitFusion)难以支持动态精度的计算,因为它们是为静态精度设计的。动态精度计算需要在运行时决定精度,这会导致硬件在精度切换时效率低下,产生数据流阻塞问题。
三、量化设计
1. 动态精度量化的前提
量化是将高精度数据(如32位浮点数)转换为低精度整数(如8位整数)的过程。公式如下:
这里,Δ是量化的缩放因子,N是位数(8位)。
原理:
缩放:将浮点数 FP32 除以量化因子 Δ,我们可以将其映射到0到255的范围内。
四舍五入:对计算结果进行四舍五入,以得到一个整数。
hp: 高精度的位数,lp: 低精度位数,hc: 从高位裁剪掉的位数,lc: 从低位裁剪掉的位数。
2. 表示能力
两个重要的衡量指标:
表示范围(RR):
取决于子张量的高精度位数 hp 和从高端裁剪掉的位数 hc,表示范围随着高端裁剪的位数 hc 的增大而减少。
表示密度(RD):衡量量化误差
表示密度表明在舍入过程中数据的精度损失情况。
3. 动态精度选择
核心思路:
-
论文假设每个子张量的数值服从拉普拉斯分布,且均值为0。这一假设意味着子张量的绝对值符合指数分布。
其中,b可以用子张量的平均值表示。
- 如果子张量的数值范围相对较小(即最大值和平均值都不太大),算法可能决定将高精度数据转换为低精度,以减少计算成本。如果子张量的数值范围较大,算法会保留高精度,避免因量化带来的精度损失。
说白了就看波动大小来判断是否要量化
动态精度选择的两步:
评估表示范围:算法首先决定子张量可以从高精度转换为低精度,具体取决于其表示范围是否足够大,以覆盖数据的最大值。以此来确定从高位裁剪掉的位数
如果表示范围不够,算法会保留高精度位数。
子张量中可能包含极端的数值(即非常大的数值),如果使用低精度时,表示范围不够大,可能会截断这些大数值。导致重要信息的丢失。
评估表示密度:接下来,算法会检查表示密度是否足够以维持精度。如果数据的方差很小,算法会选择更高的精度以避免误差过大。
这里,δ是一个超参数,用于确保模型的精度不受影响。var(Y) 是子张量 Y 的方差,RD 是表示密度。
动态精度转换的两步过程:
基于表示范围决定数据的转换方式:图中蓝色的部分表示从高端或低端裁剪掉的位数。通过衡量子张量的数值范围(最大值),算法可以决定是否可以将数据从高精度转换为低精度。换句话说,如果数据的数值范围允许,算法可以放心地减少高精度位数。
基于表示密度决定是否可以进行转换:一旦决定了如何裁剪数据位数,算法还需要确保这种转换不会带来过大的精度损失。表示密度越高,量化误差越小。如果数据的变化幅度(方差)较大,则需要保持较高的精度;而如果变化幅度较小,可以放心使用低精度进行计算。
四、Drift设计
1. Drift架构概览
图4展示了Drift加速器的总体架构。这个架构由以下几个主要组件组成:
计算引擎
- Drift的计算引擎由多个BG组成,每个BG包含一个4×4的BB阵列。每个BB可以支持1位和4位的乘法操作。
- 这种设计可以支持更灵活的精度(例如,3位、5位),比现有的加速器更灵活。
- 计算引擎还包含非线性单元和池化单元
内存层次结构
- 全局缓冲区(Global Buffer):用于控制DNN模型的输入和输出,发送激活值到计算引擎并接收输出数据。
- 权重缓冲区(Weight Buffer):存储量化后的权重,并将其提供给计算引擎。
- 索引缓冲区(Index Buffer):支持动态精度计算,跟踪特定位置的数据精度,并为调度器提供数据访问的参考。
控制器
- 包含两个组件:精度选择器和调度器。
- 精度选择器根据池化单元的结果执行动态精度算法。
- 调度器则利用精度选择器的结果,在运行时动态调整BG之间的数据流方向。
2. 数据流拆分架构
支持不同精度计算的单一systolic array会导致数据流阻塞问题,因此Drift设计了一种数据流拆分的方法,通过多个BG之间的双向连接实现灵活的互联。
数据流拆分的优势:
- Drift可以将不同精度的计算映射到不同的systolic arrays中,并保持各自的数据流不冲突。
- 如图5所示,BG之间可以通过配置数据流方向,将Drift分成多个不同的systolic arrays,每个systolic array可以独立支持一种精度的计算。(例如,左上角的systolic array可以用于高精度的矩阵乘法,而左下角的systolic array则可以处理低精度的激活和高精度的权重计算。)
3. 平衡的在线调度策略
由于每层中不同精度的数据比例变化,调度器需要动态调整每个systolic array的资源分配,以平衡延迟并减少硬件资源的闲置。
Drift采用一种贪婪调度策略,使用分析模型估计矩阵乘法的操作延迟。
假设有两个矩阵 A 和 B,GEMM的任务是计算 C=A×B,其中矩阵 A 的维度为 M×K,矩阵 B 的维度为 K×N。最终得到的矩阵 C 的维度为 M×N
调度策略的目标:
- 确保不同的精度可以同时处理,而不会相互阻塞。
- 优化硬件资源分配,最小化总的执行时间。
为了达到这个目标,调度器会根据每个精度组合的计算时间,动态调整各个 systolic array 的大小 R 和 C,以平衡不同精度下的计算负载。
总时间公式:
后边两项的物理意义没太懂,文中的解释是:由于 BG 包含 4 × 4 位块,每个位块支持 1 位和 4 位乘法,因此所需的重复次数为
公式中的每个部分含义如下:
-
Tpre:矩阵乘法开始前,权重数据预加载到计算单元的时间
-
Texe:执行时间,进行矩阵乘法操作的时间
-
pa 和 pw:激活和权重的精
-
K和 N:矩阵的维
-
R 和 C:systolic array的大小,R 是systolic array的行数,C 是systolic array的列数