Fast Trasnformer 加速BERT推理實踐
上篇BERT做NER的文章很受大家歡迎,其中不乏童鞋詢問我如何加速BERT方法的推理速度,本文就對此進行簡單的描述,主要是基於NVIDIA開源的Fast Transformer的一個實踐。
本文的主要內容如下:
-
Fast Transoformer文本分類加速實踐
-
其他可以加速推理的方法小調研
1. Fast Trasnformer 加速BERT推理環境搭建
NVIDIA的fast transorfmer加速的代碼位於:fast transormer git code
下面的很多內容,都是官方教程,我只是一個搬運工!
1.1 測試環境
OS: ubuntu16.4
CUDA: 10.0
cudnn: 7.6
cmake: 3.15
tensorflow-gpu==1.13.1
顯卡型號:RTX2070
備註: 必須要有顯卡,沒顯卡沒法繼續愉快的玩耍,cuda, cudnn版本最好也對應一下,cuda=9.x 貌似跑不起來。
1.2 必要軟件安裝
主要就是cmake的版本和TensorFlow-GPU的版本
- cmake的升級或者安裝自行百度;
- TensorFlow的版本推薦1.13.x,1.14.0筆者沒有編譯成功;
- python2或者3都可以成功編譯,但是python3在後面的實驗中需要自行解決代碼兼容問題,因爲官方是使用python2寫的,主要是print兼容問題。
1.3 編譯fast transformer
1. 3.1 下載官方代碼:
git clone https://github.com/NVIDIA/DeepLearningExamples.git
cd DeepLearningExamples/DeepLearningExamples
git submodule init
git submodule update
git 的安裝不需要寫吧
1.3.2 編譯環境
首先創建編譯目錄
mdir -p build
cd build
官方給出的demo有基於c++, tensorflow, tensorrt的支持,筆者使用的是TensorFlow的Python2,其他的自行更改,都在readme中
cmake -DSM=75 -DCMAKE_BUILD_TYPE=Release -DBUILD_TF=ON -DTF_PATH=/usr/local/lib/python2.7/dist-packages/tensorflow ..
備註:
- -DSM 是顯卡的計算能力,如果出錯,在後面的使用或者編譯中,都可能會報錯。
不同顯卡對應值:60 (P40) or 61 (P4) or 70 (V100) or 75(T4,2060,2070,2080)
因爲我使用的是2070所有參數值是75,你自己用啥顯卡自己去match就好了,其他顯卡的值在官網有,自行查閱。- DTF_PATH 是python 安裝TensorFlow的路徑,替換層自己的路徑,如果是Python3,同理。
截下來,就可以編譯了
make
如果上面正常執行的話,恭喜你,編譯成功,你離成功不遠了。
如果你出錯了,再次強調,檢查一下你的TensorFlow版本是不是1.13.1或者1.13.2, cuda ,cudnn是否版本正確,是否安裝正確。如果還是有錯,可以先谷歌。
1.4 測試fast transformer是否安裝正常
因爲疫情原因,身邊沒有機器,無法更好的進行截圖和目錄內容的展示,回工作地後再進補,大家如果編譯成功了,接着官方的教程一般就沒啥問題了。
step1
使用gemm算法找到最佳的transorfmer head計算組合,gemm的腳本在build/bin裏面,有float32 和float16的,想用那種用那種,下面以float32精度,batch_size=2, layers=12, seq_len=32, head_num=12, size_per_head=64這樣的標準bert transormer來測試
cd build
./bin/gemm_fp32 2 12 32 12 64
注意
- gemm_fp32 後面的數字分別代表batch_size,layers, seq_len, head_num, size_per_head的值,使用空格切分
- 如果要使用float16,使用對應的腳本即可
- 在我的環境中,float32, python2 ,batch_size=1的配置下會出錯,batch_size 環衛其他無問題,float16下,無問題
執行成功後,在當前目錄下,會生成gemm.的文件,然後使用下面的命令進行inference實驗
python transformer_fp32.py 2 12 32 12 64
注意
- 後面接的五個參數和gemm的參數一樣,並且要一致
- 如果使用python3 直接執行會報錯,自行進入transormer_fp32.py中修改對應的print帶來的兼容問題。
- 如果使用float16, 使用對應的腳本即可
如果一切正常,你會看到類似如下的信息
original costs xxxxxms
optimized costs xxxxms
三觀正常的話,優化後的速度會比原始速度少。
2 文本分類加速實踐
先只寫一個文本分類的demo吧,這個也是最簡單的,後續再寫一個基於序列標註任務的,其實只需要簡單的修改代碼即可實現。
2.1 訓練和加速代碼
這裏基本就是step by step了,我就按照1234來說吧。follow即可
預備
分類數據集:
隨便你用啥文本分類,中文的話,推薦THUNews
我使用的是清華的文本分類數據集,數據集的獲取和處理可以看之前的博客。https://blog.csdn.net/macanv/article/details/100927325
必要代碼:
- 官當inference代碼位於
FasterTransformer/sample/tensorflow_bert
- 文本分類代碼: 官方的,NVIDIA的,自己寫的都可以,隨便
我就以使用Google的來說吧,可能大家比較熟悉,先把bert代碼下載下來,然後吧run_classifier.py粘貼到推理demo代碼所使用的文件夾下
截下來就是具體步驟了。
步驟
1.訓練分類模型
以前咋訓練的,現在還是咋弄
2. 將float32精度的模型轉化爲float16(可選)
如果是要在float16精度上進行優化,那麼久需要先將flaot32的模型轉化爲flaot16的,轉換的腳本是
python ckpt_type_convert.py --init_checkpoint=mrpc_output/model.ckpt-343 --fp16_checkpoint=mrpc_output/fp16_model.ckpt
轉化之前,建議先將模型進行備份,轉化後,checkpoint會被替換,如果後面繼續使用float32的原始模型,那麼需要修改爲原始的chekpoint
3. 修改fast_transorfmer的lib
在fast_infer_util.py中26行,需要正確指定剛纔build下的lib路徑,這個非常重要,如果你後續需要單獨使用的時候,這裏千萬別忘了修改(別問我爲啥知道的)
4. 生成gemm
按照demo中的步驟,需要使用gemm算法生成最好的head 計算組合,這裏就很靈活了,根據自己的需求執行對應命令,例如
batch_size=2, 序列最大長度是32的話,那麼你就可以直接使用1.4 step1中的命令,
重點:將生成的gemm配置文件複製到當前推理的目錄下。
4.inference進行推理
這個步驟是使用fast transformer進行predict 測試集
python run_classifier_wrap.py --floatx=float16 --task_name=MRPC --do_eval=true --data_dir=$GLUE_DIR/MRPC --vocab_file=$BERT_BASE_DIR/vocab.txt --bert_config_file=$BERT_BASE_DIR/bert_config.json --init_checkpoint=mrpc_output/fp16_model.ckpt --max_seq_length=128 --eval_batch_size=8 --output_dir=mrpc_output
相應替換對應的參數即可
這個使用的是estimator進行的,如果使用sess.run,大體的代碼可以從這裏得到,然後將create_model 替換fiu.create_model
上訴實驗的代碼因爲身邊沒有服務器,所以暫時無法開源,如果有疑問,可以留言,我爭取能恢復,並且幫助到大家。
1.6 其他加速方法調研
- 不使用全部的12層,而是隻使用後面的n層,在交大的論文中有試驗,一般去掉前面3層不會對性能造成大的影響,但是推理速度可以提高速倍。具體任務,還需要具體分析;
- 使用TensorRT或者fast transorfmer 但是TensorRT的加速效果我一直沒有復現,會比官方報告的結果慢一倍以上。
- 模型蒸餾,這個應該是19年下半年火的不要不要的方法了吧,傳說tiny bert 效果不錯,目前也公開了源碼,有時間玩一下,也寫一下感受。
總結
本文記錄了使用NVIDIA 的fast transorfmer進行BERT推理加速的環境配置以及基於文本分類進行的實踐,一些重要的代碼在後續將會給出,最後,武漢加油,身在湖北的我瑟瑟發抖。