为什么量化可以使我的网络加速?

Why quantization matters for AI system?


引子

量化为什么可以加速你的计算?它的答案可能并不像你想象中的那么简单,在回答这个问题之前,先让我们看看下面这一组数据:

# NETWORK(batchsize=128) TOP1 Accuracy on ImageNet Inference Speed(Img/Sec)
1 Resnet-50(FP32) 73.23% 1156
2 Resnet-50(INT8) 73.10% 3787 (3.28x)
3 VGG-19(FP32) 68.41% 339
4 VGG-19(INT8) 68.38% 946 (2.79x)
5 Googlenet(FP32) 68.57% 2499
6 Googlenet(INT8) 68.12% 7282 (2.91x)

数据来源:TensorRT 量化数据。

在GPU上,对于常见的神经网络而言,将计算从 FP32 精度转换为 INT8,通常能够在保证网络精度的情况下使得推理速度提升2 ~ 3倍。这是我们对于网络量化的一般性认识,然而在这里我们希望向你展示量化的另一面,下面的数据展示了Batchsize=1时量化对于网络速度的影响:

# NETWORK(batchsize=1) TOP1 Accuracy on ImageNet Inference Speed(Img/Sec)
1 Resnet-50(FP32) 73.23% 415
2 Resnet-50(INT8) 73.10% 562 (1.35x)
3 VGG-19(FP32) 68.41% 211
4 VGG-19(INT8) 68.38% 345 (1.56x)
5 Googlenet(FP32) 68.57% 913
6 Googlenet(INT8) 68.12% 945 (1.04x)

数据来源:TensorRT 量化数据。

同样是在GPU上,当我们的Batchsize缩小到1,我们发现网络的量化性能急剧下降,甚至变得和FP32速度几乎一致,是什么样的原因导致了这一现象?量化是否能够真的加速你的应用?


定义

为了展开我们接下来的讨论,我们首先给出一些有用的 定义:

网络吞吐量 (Throughput)

也就是在一段时间内,网络所能够处理的数据总量,但是值得注意的是,对于GPU这样强大的硬件而言,你总是可以通过提高网络的Batchsize来获取更大的吞吐量。

网络延迟 (Network Latency)

也就是网络完成一次前向计算所需要花费的时间,通常它与吞吐量和Batchsize是成反比的。

硬件延迟 (Hardware Latency)

这指的是在网络完成一次前向计算过程中真正用于计算的时间,除此以外在一次典型的前向传播当中还需要考虑数据读写与内存拷贝所耗费的时间。

在上述定义的基础上,我们将深入网络的执行过程,深入探寻网络量化的完整流程。以GPU为例,我将向你粗略展示在一次网络前向传播中,究竟包含了那些必要环节:

Image
Network Executing.

正如上图中所展示的那样,对于神经网络的执行而言我们总是要在计算之外耗费一些时间,事实上对于小型网络而言耗费在执行之外的时间是不可忽视的。同时我们也要注意到GPU这样强大的硬件提供了 设备间流水线 这样的技术,这一技术在连续大批量计算过程中能够有效掩蔽读写数据的延迟,然而在要求实时性的场景中(Batchsize=1),我们仍然难以克服读写数据所带来的严重损耗。

我在这里向你澄清两个事实:

  • 硬件的吞吐量与硬件的延时往往需要采用不同的方法进行优化。
  • 对于小型网络而言,它们的网络延时可能并不是硬件延时主导的。


量化怎样加速我的计算?

为了解答这个问题,我们需要更进一步地探索硬件计算的真实面目,不妨先看看下面这个简单的求和程序:

int main(){
    int a[1000], sum;
    for(int i = 0; i < 1000; i++)
        sum += a[i];
}

哦,我知道数组 a 似乎没有正确的初始化,但这不是我们此时需要担心的事。只需要注意到这是一个整数数组的求和程序,那么就可以对它进行简单修改,从而得到一个浮点数组的求和程序:

int main(){
    float a[1000], sum;
    for(int i = 0; i < 1000; i++)
        sum += a[i];
}

现在,你一定正在思考这样的一个问题:以上两个求和程序谁更快?为什么?我将在下一章中为你解答这个问题,现在我希望你能够仔细思考一下这个问题的答案。