Skip to content

Latest commit

 

History

History
120 lines (75 loc) · 9.45 KB

ActNN.md

File metadata and controls

120 lines (75 loc) · 9.45 KB
  1. 在解决的是什么问题? 激活值占用显存较多的问题
  2. 为何成功,标志/准是什么? 不影响收敛性的情况下,能降低4倍显存值,而且是普遍适用的
  3. 在前人基础上的关键创新是什么? 最牛逼的还是数学证明,如何选取量化后的bit 数字,来保证方差最小。而且证明了梯度的方差可以作为近似(量化)的质量关键指标
  4. 关键结果有哪些? 能让 batchsize 增加一倍
  5. 有哪些局限性?如何优化? 计算过程是否比较耗时? 量化策略好像还能比 1bit 还低,比如 product 量化。
  6. 这个工作可能有什么深远的影响?

介绍

Activation compressed training (ACT) 是一个非常有前景的方法,可以减少训练的内存消耗。ACT 通过量化方法压缩激活值到低比特数值精度。首次在 BLPA 里提出,后来又有 TinyScript 扩展到了非均匀的量化策略。这些方法在训练 ResNet-50 时使用了4bit 的激活值。

但是有几个劣势:

  1. ACT 方法下的收敛性没有完全搞清楚(出了在强 mean-field 假设的限制下)
  2. 之前的工作聚焦在特定的架构下,例如ResNet的 pre-activation 的定制版本,限制了通用性
  3. 现存的量化策略并不是专门给 ACT 设计的,压缩率不理想

提出的 ActNN,克服了上述所有问题。它存储随机量化的激活值来计算梯度。理论上,可以把 ActNN计算出的梯度当作全精度下(FP radient)梯度的随机近似。我们展示了 ActNN 梯度时 FP 梯度的无偏见近似。证明了 ActNN 在通用模型架构上的收敛性。所以 ACT 有理论保证可以解决通用问题

本文贡献主要三点:

  1. ACt的通用收敛理论
  2. 感知异构性(feature维度,采样,层)的量化策略,达到2bit压缩
  3. PyTorch 里高效激活值压缩的实现

我们通过梯度偏差上精确的表达式,刻画了量化对收敛的影响。更好的量化策略减少了梯度偏差,可以用低比特达到满意的收敛性。受理论启发,设计了创新的量化策略,可以利用激活值在 feature 维度,数据样例和层上的异构性。这包括了一个 group 粒度的量化器和一个细粒度混合精度的算法,可以近似减少给定内存限制下的梯度偏差。在多种不通任务下,包括图片分类,语义分割和对象检测上,ActNN 把激活值压缩到2bit,精度损失小于 0.5%。即使只有 1.25 bit,也能有很好的收敛和结果。这很大程度提高了前人的工作,只能在4bit 下收敛。

效果:ActNN 减少了12倍的激活值内存,可以允许在 GPU 上训练 6.6到14倍大的batchsize。它允许不增加额外计算资源的情况下,训练更大的模型。比如把 ResNet 扩展到6.4倍深,或3.7倍宽,或 3.1倍更高精度。

相关工作

量化训练(Quantized Training) :量化感知训练(QAT) 或 完全量化的训练,目标是在推理或训练时减少计算的代价,通过量化来实现。一个副作用是训练的内存开销会减少。但是 QAT 是一个更有挑战的任务,因为需要计算的内核直接支持量化的 tensor。与之对比, ACT 只需要考虑存储,可以利用更灵活的量化策略来做更好的压缩。而且 ACT 和 QT 是互补的。一个利用 QT 来加速训练,ACT 用来进一步减少内存开销

模型/梯度压缩:模型压缩和梯度压缩压缩了权重和梯度,减少了存储和通信的开销。然而,激活值与权重和梯度相比,有不同的属性,它有一个“sample”的轴。而且,ACT对压缩速度更敏感,因为激活值可以在过程中压缩,通常比权重和梯度更大(这个应该是cv里,nlp里不是)。ActNN的压缩策略就是给有这些特定属性量身定制的。

内存高效的训练系统:Gradient checkpointing 妥协了计算来获得更小内存,方法是在前向过程中丢掉一些激活值,在 backward 里需要时重新计算。交换(Swapping)技术利用了 CPU 上的大内存,把 GPU 上的 tensor 交换到 CPU 上。模型并行的训练,把模型拆分到GPU上,所以每个 GPU 只存储部分layers。所有这些方法通过在 GPU 上存储更少的 tensor 来节省内存。与之对比,ActNN 是压缩保存的 tensors,可以和这些方法互补。

3. 公式和理论

看八太懂啊

收敛时的误差会被梯度的方差所限制。推导出了使用量化压缩后,随机梯度下降计算出的方差= mnibatch采样时随机梯度下降的方差 + 有损压缩额外引入的方差。说明有损压缩带来的方差远小于随机梯度下降带来的方差即可,这样不影响收敛性

4. 压缩策略

从图3可以看到 ResNet50 中激活值的异构性:

a) conv_2_2_1这个层在不通分组(per-group) 的范围下直方图,可以看到主要集中在前面 b) 同一层中,样本级别的直方图敏感度,看到在少量层上敏感 c)每个层上各维度的敏感性,看到最敏感的是最后一层?。Y轴是敏感性,缺 dimension 这个维度呢?

上述敏感度,是用它提供的公式来刻画的:w(l,n)

4.1 Per-group 量化

为了解决 feature 的不通维度上数值的范围差异,提出了分组的量化策略。 给定一个激活值 tensor,把它分到 hni 个组里,每个组有 G 个元素。数量会被量化到 b bit,或 B=2^b-1。对于每个元素,可以计算出最小值,最大值和激活值的缩放:

这样把输入缩到 [0, B] 上。利用随机近似来处理成整数。在反向传播时,激活值可以反量化。这里利用了随机近似的非偏向性,所以量化前后的期望是一致的。

已有量化策略对每个 Tensor 使用单个范围和零点,可以看作是单个组。这样 Range 只能取最大的那个 R=max(ni)Rni。而图3 里介绍了,大部分组的 range 是比 R 要小很多的。这样就增大了方差(Variance)。

实际设置 G 为 256 ,用bfloat16来 存储每个组范围和零点,这样每个组额外消耗 32 bit。

4.2 细粒度、混合精度

想进一步减小方差,ActNN 使用混合精度量化策略:针对每次 sample 和 每层,适应性选取数值精度。sample 里是这一次 iteraion 里的数据特点,而每层是不通类型的 op,对数值精度的敏感性不通。

虽然看不懂,但是它的原理是啥?忽略掉不重要的变量,只研究主要变量对结果的影响?

混合精度可以极大地减小梯度的方差。

4.3 运行时适应

为了最好地利用数据的特点,ActNN 在运行时调整混合精度策略。每个 SGD 的一次迭代里,发生两阶段的调优:

  1. (每个 sample 上分配一次) 每层的forward 时,计算并存储每个 sample 里的敏感性。计算出在当前层的固定bit的预算下,对每次 sample 的最佳桶位数。通过解问题10.
  2. (每层分配) 在结束 backward 时,对所有的层,解问题10,然后设置整体 b 为 sum(b)

问题十是一个离散优化问题,可以通过 DP 来精确解决。但是代价比较大,所以使用贪心算法,当通过二分堆来选一个最优解,复杂度是 O(NL log2(NL)),N 是batchsize,L 是模型深度

最终,敏感度 wn(l) 可能取决于每个采样里梯度的量级,我们压缩时并不知道。ActNN 用了两个方法来预估梯度的量级。第一个是用上一次 epoch 里的 stale gradient magnitude。第二个是用多个 sample 之间的梯度量级的移动平均。两个在实际中效果都很好。

5 实现

有 PyTorch 里一些层的实现,用户可以直接用 ActNNModule 来包一下自己的模型即可

实现了高效的 CUDA kernel 来压缩和解压缩,可以把浮点数量化为整数,压缩到bit流里

对比了 CheckMate,MONet,DTR,SwapAdvisor,Capuchin,BLPA 和 ActNN,其中有一些方法需要训练前先解决一波优化问题,有的需要花费小时级别的时间。

而 ActNN 不需要

优化级别:

PyTorch 里使用了 caching allocator,复用了 GPU buffer,速度快但是会有严重的碎片问题。当要分配大的 tensor 时,可以关闭掉。

L1:只给 conv 层做分组量化 L2 : 所有层 L3: L2 + 细粒度混合精度优化 L4: L3 + swapping L5: L4 + defragmentation

ActNN 可以和 AMP 结合,对进度无影响

6 实验

表格里统计了各类 CV 模型里 activation 的量级,大概占比内存的 90%,所以用 ActNN 非常有用

问题:

  1. 上述 CUDA kernel 里,还可以把数据变成bit stream ?
  2. 按照不同类 op,可以理解为是固定类型的? 不是的,是根据公式要流式计算敏感性
  3. 那 sample 是如何做呢?需要先读取一遍sample 数据吗? forward 时记录即可
  4. 上述三种方法都是处理完一次 iteration,再优化量化策略?还是说每次压缩前都处理一下?前者,只有梯度的量级是逐步更新的
  5. 为何对 GPU 友好?

我阅读的结论:

  1. 此算法主要用在 CV 里,因为图片是三维的,activation 数据比较大。而且它的数学公式,跟 SGD 有关?

有趣有趣,与互联网领域的文本压缩或时序数据的压缩对比一下: 共同点:都依赖数据的变化特点,需要考虑压缩后尽量减小决策结果的影响 差异点:ML里具体数值不重要,方差重要,所以用整数桶来表示数据(量化)。而时序数据是通过描述当前数据与前一条/块数据的差异来压缩,需要能还原为准确的原始数值