speed-up

之前文章中介绍了通过模型压缩来加速其推理速度的主要思路,并就知识蒸馏总结了三篇内容,分别是:模型替换之bert-of-theseus知识迁移看样本下菜的FastBERT。本文总结两种与模型无关的加速方案。

训练加速

训练加速的主要方法包括pipeline 和混合精度,其中pipeline是指通过构造一个input pipeline将数据IO与GPU计算分开,从而避免GPU因IO而空闲,这个问题不是本篇重点,想进一步了解的可以参考tensorflow数据读取机制-何之源Doc-tf-data-dataset

混合精度

混合精度是指训练时在模型中同时使用 16 位和32位浮点类型,从而加快运行速度,减少内存使用的一种训练方法。通过让模型的某些部分保持使用 32 位类型以保持数值稳定性,可以缩短模型的单步用时,而在评估指标(如准确率)方面仍可以获得同等的训练效果。(tf doc)简单说就是开启混合精度,既能更省显存又能加速训练,保证性能的前提下,偶尔还能提高性能,真是又省又快又好,了解更多混合精度相关知识,可以参考浅谈混合精度训练.
然而很早之前笔者就知道开启混合精度的好处了,在pytorch 下有apex 可以很方便的开启,但是在keras(tensorflow 1.x) 下尝试了多次,也没能找到正确的方法,最近笔者又一次尝试,终于找到了正确的姿势,这里也分享一下。

对应的软硬件要求

tensorflow要求版本在1.14+ ,对应的显卡需要算力(compute capability)在7及以上, 可以在cuda-gpus#compute查看对应型号卡的算力

如何开启

对应代码中,只需要增加一行代码,修改一下optimizer即可。不过仍有两点非常需要注意:

  1. 修改optimizer最好在build model前完成,否则某些情况下可能会报错。
  2. optimizer需要是tf.train.Optimizer or tf.keras.optimizers.Optimizer继承来的,不支持keras 原生的optimizer。
1
2
3
4
5
6
7

...
opt = ...
opt = tf.train.experimental.enable_mixed_precision_graph_rewrite(opt) # rewrite opt

# build_model
...

当在打印信息中看到 tensorflow/core/grappler/optimizers/auto_mixed_precision.cc相关信息,则说明已成功开启混合精度。

1
2
3
...
2021-08-04 07:36:24.231900: I tensorflow/core/grappler/optimizers/auto_mixed_precision.cc:1816] Running auto_mixed_precision graph optimizer
...

一些测试结果

笔者在V100 下用bert-base 做了部分测试,测试结果如下:

batch_size=32, maxlen=128

epoch 1epoch 2epoch 3epoch 4epoch 5
开启前:
277s246s244s246s244s
164ms/step147ms/step146ms/step147ms/step146ms/step
bset acc:0.57
开启后:
235s200s201s200s201s
140ms/step120ms/step121ms/step120ms/step121ms/step
best acc:0.576

batch_size=64, maxlen=128

epoch 1epoch 2epoch 3epoch 4epoch 5
开启前:
234s202s201s203s203s
281ms/step242ms/step241ms/step244ms/step244ms/step
best acc:0.567
开启后:
180s141s140s140s141s
216ms/step169ms/step168ms/step168ms/step169ms/step
best acc:0.571

可以看到,batch size越大,加速比越可观,约能节省1/3的训练时间,同时,性能不会出现明显下降甚至可能也会高一点点。
另外,测试使用的bert 是keras 代码,其中有一条日志是converted 1265/17548 nodes to float16 precision,所以约有不到10%的节点使用了半精度?所以猜测使用半精度的节点越多加速比越可观。

推理加速

推理时通常需要我们提供一个SDK或一个API 服务,这里我们只讨论API 服务的情况。
而API 服务通常有两种做法:

  1. 在server 端load 模型,然后直接预测给出结果;
  2. backend 调用tf-serving ,模型的预测由tf-serving 来提供,其余的(数据的预处理,结果的后处理等)则在backend 端进行。tf-serving 具有热更新,支持多模型多版本,异步调用,高可用等特性,所以也推荐使用tf-serving。使用了tf-serving后,完整的路线变为:
    client –> backend –> rpc/rest –> tf-serving
    其中tf-serving 提供了两种形式的api:restful api 和 grpc
    对应的demo 代码可以查看serving

测试

关于头图

可爱修狗

对比学习心路历程
faster-decoder之 decoder解码加速