最近又被一週一更的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就能夠了性能