最近又被一周一更的flag打脸,一是拉来了外援助阵专栏(之后会愈来愈多的!),二是本身想探索新的故事线(好比NLP+CV的任务),三是工做太忙(懒)。git
最近开始接触BERT Inference的优化,这篇文章主要总结一下知识点github
1. 简介
Inference提速的重要性就没必要说了,目前主流的优化方式有如下几种:网络
- 分布式计算(CPU):将底层的矩阵运算并行化
- 混合精度(GPU):理论上INT8优化可提高4倍、FP16可提高2倍
- 重写Kernel(GPU):使用GPU计算时,每次运算(好比TF中的operation)都要通过几个流程:CPU在GPU上分配显存 -> CPU把数据发送给GPU -> CPU启动GPU kernel -> CPU把数据取回 -> CPU释放GPU显存。复杂的模型每每须要大量的operation,形成屡次显存读写。而若是把多个kernel合并重写就能够避免这种额外开销
接下来会介绍一下Pytorch、Tensorflow、C++配合不一样设备可用的优化方案,各位能够根据业务须要和经济实力选择适合本身团队的。多线程
另外在开始正文前先介绍一些周边名词,方便以后的理解:分布式
- BLAS:Basic Linear Algebra Subprograms,一个线性代数计算的API标准,Netlib用fortran语言编写了一个BLAS计算库
- LAPACK:基于BLAS,Netlib用fortran语言编写的计算库,优于BLAS
- Intel MKL:基于BLAS、LAPACK和另一些计算库编写的数学计算库,C++和Fortran语言编写,基于OpenMP可进行多线程优化。后来针对深度神经网络又出了一个MKL-DNN。Pytorch就是基于MKL的
- Eigen:基于BLAS、LAPACK和另一些计算库编写的数学计算库,C++语言编写,基于OpenMP可进行多线程优化。支持MKL做为底层,支持CUDA。MKL和Eigen是两个经常使用的高级计算库,其中MKL的速度更快一些,但Eigen更容易上手,并且随着优化速度也在逼近MKL。Tensorflow就是基于Eigen的
- CuDNN:用于深度神经网络的GPU加速库,支持并行计算,Pytorch的GPU实现基于CuDNN,TF也有提供基于cudnn的实现
- CuBLAS:用cuda实现的GPU BLAS计算库
2. 优化方案(以BERT为例)
2.1 经济CPU
- Tensorflow提供C++,Java API,建议把训练好的模型用更高效的语言部署。由于是基于eigen,应该能够设置线程数并行化矩阵运算。
- Pytorch好像只有C++ API,经过torchlib调用,能够设置线程数并行化矩阵运算。
- 厉害的大佬能够基于MKL或者Eigen本身撸一份,好比知乎的几个大牛就写了一个CuBERT,支持load pb格式的BERT,看性能比Tensorflow提高很多。
2.2 土豪GPU
- Tensorflow XLA,能够在编译阶段合并OpKernel
- Tensorflow、Pytorch都支持FP16优化
- TensorRT是NVDIA提供的库,也是对OpKernel进行融合,同时支持INT8和FP16优化
- Faster Transformer是NVIDIA专门针对transformer写的Kernel,极速爆表,支持FP16和TensorRT,提供C++、TF接口,若是拥有GPU的话你还在等什么:
3. 建议
对线上要求很高的话,仍是用GPU+faster transformer,若是不高,那也不用本身手撸一份纯C++的代码,用TF、Pytorch的C++ API就能够了性能