咱们好啊,我是董董灿。

优化有时分真的很头疼,绞尽脑汁的想怎样做算法等价,怎样把神经网络各层指令流水起来,在确保整网精度的一起,又有高功能。

但有时做了半天,却发现流水根本就流不起来,总是不可思议地被卡住。

真的是一顿操作猛如虎,回头一看原地杵。

神经网络推理加速入门——转换提前

今日介绍一种神经网络的功能优化办法。它不需求懂特深奥的算法常识,就能做到整个优化系统,大到网络,小到算子的功能的成倍提高。

而且绝对是成倍的功能提高,而且显而易见的算法等价。

怎样做呢?很简略,只需求改一下算子的先后调用顺序就行。

布景

在做AI推理或许练习时,大部分情况下一个神经网络中的一切层(Layer)的核算数据类型是相同的。

比方为了网络有更好的辨认精度,神经网络中的运算可以运用高精度的浮点数,如 float32,简称 FP32。

但有时为了功能,略微损失一点辨认精度也能接受,此时可能会运用 float16,简称FP16, 也便是半精度数据类型来做运算。

FP32 和 FP16 的区别在于,前者数据位宽是后者的两倍,因而表示相同的数据的时分,前者的精度更高,但内存占用也更大。

比方一起存储一张图片,假如运用 FP32的话,可能会占用1MB的内存,但假如运用FP16来存储,只占0.5MB的内存。

咱们可能听说过混合精度推理、混合精度练习。这儿说的混合,指的便是精度混合。比方一个神经网络中存在多种数据类型。

为什么可以做混合精度的推理或练习呢?

一个神经网络就像是一个大厦,由一层一层的算法搭建而成,每一层的算法可能不同。不同的算法对数据精度的灵敏程度不同。

有很多算法对数据精度不灵敏,比方 transpose, gather, scatter等,这类算法都是数据转移操作,也便是纯IO操作。他们不需求进行数据核算,无需考虑数据在做加法时分的溢出处理等情况。

而有些算法对数据精度很灵敏,典型的比方conv2d算法,它需求做大量的乘累加操作,数据的累加很简单呈现溢出,此时需求用更高位宽的数据来接纳累加成果。

假如把操作 FP32 比作需求转移32块砖的话,那么 FP16 便是只需求转移 16块砖。很明显,转移16块砖比转移32块砖,在其他条件不变的情况下,要省时省力。

因而,在神经网络尤其是混合练习或推理的网络中,假如遇到了一些数据转移算法转移的是 FP32,那么是很有时机只让他搬16块砖(FP16)的。

那么详细怎样做呢?

首先简化一个神经网络,假设一个神经网络有如下结构:

神经网络推理加速入门——转换提前

在这个假想的网络中,卷积层(conv2d)核算的输出是 FP32,然后送给transpose 层进行数据转移,transpose由所以纯IO算法,因而它的输出也是FP32。

transpose的输出送给下一层cast,cast负责将FP32的数据转化为FP16, 因而cast 的输出是FP16。然后FP16的数据送给接下来的层进行运算。

不知有没有发现,在这个网络中,transpose 算法先转移了FP32的数据,然后交给了 cast 进行数据类型转化,转化成了更低位宽的 FP16。

可是由于 transpose 是纯IO运算,对数据类型不灵敏,因而,咱们完全可以将cast算子提早到 transpose 之前,如此的话,transpose 只需求做 FP16 的数据转移

转化之后的网络如下:

神经网络推理加速入门——转换提前

这样做的成果便是:整个网络的核算是等价的,可是 transpose 算子却由本来进行 FP32 的数据转移,变成了 FP16 的数据转移。对 transpose而言,其IO功能表现是成倍的提高。

这仅仅举一个很简略的例子。

而实际上,在真实的网络中,运用此办法可以优化成功的算法有时不仅仅是一个简略的 transpose,而是一个很大的网络片段。

由此可见,仅仅将 cast 提早这一个简略的操作,就能使整网的功能提高一倍。

这个办法很简略,很有用,也很简单施行。可是在实际进行网络优化的时分,有时却会被疏忽。

可以运用这一优化的网络有必要满意以下两个条件:

  • 有必要是混合精度的网络
  • 由高位宽转低位宽的cast 算子前存在 IO 型算子

在咱们绞尽脑汁运用一些高级的技巧,如模型并行、层层流水来做网络优化的一起,无妨扩大视角,着眼全图,看看整网是否满意上面的条件,没准只一眼,就能发现这一最简略有用的优化点,从此百分比的提高网络功能,不是梦!