深入淺出騰訊BERT推理模型--TurboTransformers

Overview

TurboTransformers是騰訊最近開源的BERT推理模型酱固,它的特點(diǎn)就是一個(gè)字饥悴,快逗鸣。本人用BERT(huggingface/transformers)在V100上做了測試乍构,測試結(jié)果和官宣的基本一致:TurboTransformers的推理速度要比Pytorch快上1~4倍。

圖片來源:https://github.com/Tencent/TurboTransformers

它之所以快柳譬,是因?yàn)樗菍S糜贐ERT的輕量級推理模型喳张。

分層

不管是計(jì)算機(jī)的硬件、軟件征绎,還是現(xiàn)在的深度學(xué)習(xí)蹲姐,它們都遵循著一個(gè)很重要的設(shè)計(jì)思想--分層:

  • 用簡單的代碼(或電路)來實(shí)現(xiàn)一個(gè)基本功能組件。
  • 用幾個(gè)基本組件組合成一個(gè)功能更強(qiáng)的復(fù)雜組件人柿。
  • 從簡單到復(fù)雜柴墩,像搭積木一樣,一層層地搭建出擁有很強(qiáng)功能的組件凫岖。

開發(fā)者只需要基于PyTorch的幾個(gè)基本組件就能搭建出BERT模型江咳,而且這些組件本身對他們來說都是透明的。正因如此哥放,PyTorch才越來越受到研究者青睞歼指。

BERT模型的基本組件

分層設(shè)計(jì)的優(yōu)點(diǎn)很多,例如甥雕,可以簡化問題踩身、降低創(chuàng)新門檻、加速開發(fā)等社露,但它的缺點(diǎn)也很明顯:

  • 流程固定化
  • 存在中間層延遲

深度神經(jīng)網(wǎng)絡(luò)里有個(gè)經(jīng)典套路:一個(gè)激活函數(shù)層后面緊跟著一個(gè)dropout層挟阻。PyTorch需要lanuch兩個(gè)GPU kernel程序來完成這兩步計(jì)算。

F.dropout(F.relu(x))

實(shí)際上峭弟,這兩項(xiàng)計(jì)算都是element-wise的附鸽,是可以合并成一個(gè)kernel的。但目前來說瞒瘸,不管是PyTorch坷备,還是其他的通用訓(xùn)練框架,它們都很少有提供這種融合計(jì)算的API情臭。

至于中間層延遲省撑,最經(jīng)典的要屬“hello world”程序。雖然只有幾行代碼俯在,但實(shí)際上要經(jīng)過的中間層數(shù)根本數(shù)不過來丁侄。

你可以閱讀深入淺出PyTorch(算子篇)來了解下矩陣相乘這個(gè)最基本的計(jì)算在PyTorch里要經(jīng)過多少個(gè)中間層。

分層展開

要想將程序的低延遲最大化朝巫,就需要把分層的代碼完全展開,并重構(gòu)代碼石景。典型例子就是嵌入式系統(tǒng)劈猿,為了實(shí)現(xiàn)某種需求拙吉,它可以打破應(yīng)用程序、程序庫揪荣、操作系統(tǒng)甚至是硬件設(shè)備的界限筷黔,打造一個(gè)軟硬件一體化產(chǎn)品。

這種分層展開的設(shè)計(jì)模式當(dāng)然也有它的局限性:專用仗颈。由于高度定制化佛舱,它通常只能用于完成某個(gè)特定功能。低延遲和專用化是呈絕對的正相關(guān)的挨决。

TurboTransformers就是采用這種設(shè)計(jì):只實(shí)現(xiàn)BERT模型前向傳播所需要的算子请祖,并融合那些可以合并的算子。

turbo.Tensor

首先脖祈,它用CUDA開發(fā)了一個(gè)輕量級的tensor計(jì)算庫肆捕,所謂的輕量級,指的是不用考慮反向傳播盖高、稀疏矩陣等操作慎陵,只實(shí)現(xiàn)BERT前向傳播所必需的operator。

雖然tensor庫是用C++寫的喻奥,但考慮到python在AI開發(fā)中的地位席纽,它用pybind11將C++ API暴露給前端的python Tensor類。

# turbo_transformers/python/pybind.cpp
 72   py::class_<core::Tensor>(m, "Tensor")                      
 73       .def_static("from_dlpack",
 74                   [](py::capsule capsule) -> std::unique_ptr<core::Tensor> {
 75                     auto tensor = (DLManagedTensor *)(capsule);
 76                     PyCapsule_SetName(capsule.ptr(), "used_tensor");
 77                     return absl::make_unique<core::Tensor>(tensor);
 78                   })
 79       .def("to_dlpack",
 80            [](core::Tensor &tensor) -> py::capsule {
 81              auto *dlpack = tensor.ToDLPack();                    
 82              return py::capsule(dlpack, "dltensor", DLPack_Capsule_Destructor);
 83            })
 84       .def("n_dim", &core::Tensor::n_dim)
 85       .def("shape", &core::Tensor::shape)

從預(yù)訓(xùn)練模型(PyTorch)那遷移參數(shù)時(shí)撞蚕,turbo.Tensor不能直接對接torch.Tensor润梯,需要先將PyTorch的參數(shù)轉(zhuǎn)成dlpack格式, 再通過from_dlpack()將這些數(shù)據(jù)導(dǎo)入生成TurboTransformers tensor。除了dlpack之外诈豌,還支持*.npz文件格式仆救。

圖片來源:https://github.com/Tencent/TurboTransformers

turbo.xxxlayer

TurboTransformers用CUDA重構(gòu)了Embedding、self-attention矫渔、intermediate彤蔽、output、LayerNorm和pooler等layer庙洼。turbo.layer不僅代碼結(jié)構(gòu)簡潔顿痪,overhead少,還合并了一部分算子油够。

圖片來源:https://www.oschina.net/news/115146/tencent-wechat-opensource-turbotransformers

這里以intermediate layer為例蚁袭,來分析這些算子的特點(diǎn)。

turbo_transformers/layers/bert_intermediate.cpp

intermediate layer的實(shí)現(xiàn)比較簡單:一個(gè)Linear layer后面緊跟著一個(gè)gelu activation layer石咬。

PyTorch的intermediate layer的會lanuch 3個(gè)kernel來完成這部分計(jì)算:

  • #1: y = input.matmul(weight)
  • #2: y = y + bias
  • #3: y = gelu(y)

由于#2和#3都是element-wise kernel揩悄,turbo把它們進(jìn)行了融合--AddBiasAct(),相同的計(jì)算操作鬼悠,只需要lanuch 2個(gè)kernel删性,計(jì)算速度當(dāng)然更快亏娜。

turbo_transformers/layers/kernels/mat_mul.cpp

和PyTorch一樣,turbo的MatMul算子也是調(diào)用cuBLAS來進(jìn)行矩陣運(yùn)算蹬挺,而且turbo還啟用了Tensor Core來加速計(jì)算(CUBLAS_TENSOR_OP_MATH)维贺。

總結(jié)

到此,本文基本上講清了TurboTransformers的速度優(yōu)勢來源巴帮,由于篇幅所限溯泣,不能分析所有的算子。BERT的核心模塊是self-attention榕茧,如果想了解更多垃沦,可以閱讀深入淺出Transformer


歡迎關(guān)注和點(diǎn)贊雪猪,你的鼓勵(lì)將是我創(chuàng)作的動(dòng)力

歡迎轉(zhuǎn)發(fā)至朋友圈栏尚,公眾號轉(zhuǎn)載請后臺留言申請授權(quán)~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市只恨,隨后出現(xiàn)的幾起案子译仗,更是在濱河造成了極大的恐慌,老刑警劉巖官觅,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纵菌,死亡現(xiàn)場離奇詭異,居然都是意外死亡休涤,警方通過查閱死者的電腦和手機(jī)咱圆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來功氨,“玉大人序苏,你說我怎么就攤上這事〗萜啵” “怎么了忱详?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跺涤。 經(jīng)常有香客問我匈睁,道長,這世上最難降的妖魔是什么桶错? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任航唆,我火速辦了婚禮,結(jié)果婚禮上院刁,老公的妹妹穿的比我還像新娘糯钙。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布超营。 她就那樣靜靜地躺著鸳玩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪演闭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天颓帝,我揣著相機(jī)與錄音米碰,去河邊找鬼。 笑死购城,一個(gè)胖子當(dāng)著我的面吹牛吕座,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瘪板,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼吴趴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了侮攀?” 一聲冷哼從身側(cè)響起锣枝,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兰英,沒想到半個(gè)月后撇叁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畦贸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年陨闹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薄坏。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趋厉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胶坠,到底是詐尸還是另有隱情君账,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布涵但,位于F島的核電站杈绸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏矮瘟。R本人自食惡果不足惜瞳脓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澈侠。 院中可真熱鬧劫侧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至审姓,卻和暖如春珍特,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背魔吐。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工扎筒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人酬姆。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓嗜桌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辞色。 傳聞我的和親對象是個(gè)殘疾皇子骨宠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容