分享 | 美團(tuán)深度學(xué)習(xí)系統(tǒng)的工程實(shí)踐
背景
深度學(xué)習(xí)作為AI時(shí)代的核心技術(shù),已經(jīng)被應(yīng)用于多個(gè)場(chǎng)景。在系統(tǒng)設(shè)計(jì)層面,由于其具有計(jì)算密集型的特性,所以與傳統(tǒng)的機(jī)器學(xué)習(xí)算法在工程實(shí)踐過(guò)程中存在諸多的不同。本文將介紹美團(tuán)平臺(tái)在應(yīng)用深度學(xué)習(xí)技術(shù)的過(guò)程中,相關(guān)系統(tǒng)設(shè)計(jì)的一些經(jīng)驗(yàn)。
本文將首先列舉部分深度學(xué)習(xí)算法所需的計(jì)算量,然后再介紹為滿(mǎn)足這些計(jì)算量,目前業(yè)界比較常見(jiàn)的一些解決方案。最后,我們將介紹美團(tuán)平臺(tái)在NLU和語(yǔ)音識(shí)別兩個(gè)領(lǐng)域中,設(shè)計(jì)相關(guān)系統(tǒng)的經(jīng)驗(yàn)。
深度學(xué)習(xí)的計(jì)算量
Model | Input Size | Param Size | Flops |
---|---|---|---|
AlexNet | 227 x 227 | 233 MB | 727 MFLOPs |
CaffeNet | 224 x 224 | 233 MB | 724 MFLOPs |
VGG-VD-16 | 224 x 224 | 528 MB | 16 GFLOPs |
VGG-VD-19 | 224 x 224 | 548 MB | 20 GFLOPs |
GoogleNet | 224 x 224 | 51 MB | 2 GFLOPs |
ResNet-34 | 224 x 224 | 83 MB | 4 GFLOPs |
ResNet-152 | 224 x 224 | 230 MB | 11 GFLOPs |
SENet | 224 x 224 | 440 MB | 21 GFLOPs |
數(shù)據(jù)來(lái)源
上表列舉了,ImageNet圖像識(shí)別中常見(jiàn)算法的模型大小以及單張圖片一次訓(xùn)練(One Pass)所需要的計(jì)算量。
自2012年,Hinton的學(xué)生Alex Krizhevsky提出AlexNet,一舉摘下ILSVRC 2012的桂冠后,ILSVRC比賽冠軍的準(zhǔn)確率越來(lái)越高。與此同時(shí),其中使用到的深度學(xué)習(xí)算法也越來(lái)越復(fù)雜,所需要的計(jì)算量也越來(lái)越大。SENet與AlexNet相比,計(jì)算量多了近30倍。我們知道,ImageNet大概有120萬(wàn)張圖片,以SENet為例,如果要完成100個(gè)epoch的完整訓(xùn)練,將需要2.52 * 10^18的計(jì)算量。如此龐大的計(jì)算量,已經(jīng)遠(yuǎn)遠(yuǎn)超出傳統(tǒng)的機(jī)器學(xué)習(xí)算法的范疇。更別說(shuō),Google在論文《Revisiting Unreasonable Effectiveness of Data in Deep Learning Era》中提及的、比ImageNet大300倍的數(shù)據(jù)集。
物理計(jì)算性能
面對(duì)如此龐大的計(jì)算量,那么,我們業(yè)界當(dāng)前常用的計(jì)算單元的計(jì)算力是多少呢?
- CPU 物理核:一般浮點(diǎn)運(yùn)算能力在10^10 FLOPS量級(jí)。一臺(tái)16 Cores的服務(wù)器,大致上有200 GFLOPS的運(yùn)算能力。實(shí)際運(yùn)行,CPU 大概能用到80%的性能,那就160 GFLOPS的運(yùn)算能力。完成上述SENet運(yùn)行,需要182天。
- NVIDIA GPGPU: 目前的V100,單精度浮點(diǎn)運(yùn)算的峰值大概為14 TFLOPS, 實(shí)際運(yùn)行中,我們假設(shè)能用到50%的峰值性能,那就是7 TFLOPS,需要4天。
根據(jù)以上數(shù)據(jù)結(jié)果可以看出:在深度學(xué)習(xí)領(lǐng)域,GPU訓(xùn)練數(shù)據(jù)集所需要耗費(fèi)的時(shí)間,遠(yuǎn)遠(yuǎn)少于CPU,這也是當(dāng)前深度學(xué)習(xí)訓(xùn)練都是采用GPU的重要原因。
業(yè)界的解決方案
從前面的計(jì)算可知,即使使用GPU來(lái)計(jì)算,訓(xùn)練一次ImageNet 也需要4天的時(shí)間。但對(duì)于算法工程師做實(shí)驗(yàn)、調(diào)參而言,這種耗時(shí)數(shù)天的等待是難以忍受的。為此,目前業(yè)界針對(duì)深度學(xué)習(xí)訓(xùn)練的加速,提出了各種各樣的解決方案。
異構(gòu)計(jì)算的并行方案
數(shù)據(jù)并行(Data Parallelism)
數(shù)據(jù)并行,即每個(gè)計(jì)算單元都保留一份完整的模型拷貝,分別訓(xùn)練不同的數(shù)據(jù),經(jīng)過(guò)一個(gè)Iteration或若干個(gè)Iteration后,把各個(gè)計(jì)算單元的模型做一次同步。這是最常見(jiàn)的深度學(xué)習(xí)訓(xùn)練方式,好處在于邏輯簡(jiǎn)單、代碼實(shí)現(xiàn)方便。
模型并行(Model Parallelism)
模型并行,即各個(gè)計(jì)算單元存儲(chǔ)同一層模型數(shù)據(jù)的不同部分,訓(xùn)練相同的數(shù)據(jù)。相對(duì)于數(shù)據(jù)并行,因?yàn)楦鱾€(gè)運(yùn)算單元每訓(xùn)練完一層神經(jīng)網(wǎng)絡(luò),就必須要同步一次,頻繁的同步通信導(dǎo)致系統(tǒng)不能充分地利用硬件的運(yùn)算能力,所以更為少見(jiàn)。但是在一些業(yè)務(wù)場(chǎng)景下,Softmax層需要分類(lèi)的類(lèi)別可能會(huì)有很多,導(dǎo)致Softmax層太大,單個(gè)計(jì)算單元無(wú)法存儲(chǔ),這個(gè)時(shí)候,需要把模型切割成若干部分,存儲(chǔ)在不同的運(yùn)算單元。模型并行常見(jiàn)于NLU、推薦、金融等領(lǐng)域。
流式并行(Stream Parallelism)
流式并行,即每個(gè)計(jì)算單元都存儲(chǔ)不同層的模型數(shù)據(jù),訓(xùn)練相同的數(shù)據(jù)。如上圖所示,GPU1只負(fù)責(zé)第一層神經(jīng)網(wǎng)絡(luò)的計(jì)算,GPU2只負(fù)責(zé)2~5層神經(jīng)網(wǎng)絡(luò)的計(jì)算,GPU3只負(fù)責(zé)第6層的計(jì)算。流式并行的好處在于每個(gè)運(yùn)算單元之間的通信和計(jì)算重疊(overlap),如果配置得當(dāng),可以非常充分地利用硬件資源。缺點(diǎn)在于,根據(jù)不同的模型,需要平衡好各個(gè)計(jì)算單元的計(jì)算量,如果配置不好,很容易形成“堰塞湖”。如上圖所示,很有可能出現(xiàn)GPU1 負(fù)責(zé)的運(yùn)算量太少,而GPU2 負(fù)責(zé)的運(yùn)算量太多,導(dǎo)致GPU1 和GPU2 之間堵塞住大量的Mini-batch,更常見(jiàn)于線(xiàn)上環(huán)境。
混合并行(Hybrid Parallelism)
混合并行,即上面提到的并行方式的混合。如對(duì)于一些圖像識(shí)別任務(wù)來(lái)說(shuō),可能前幾層使用數(shù)據(jù)并行,最后的Softmax層,使用模型并行。
異構(gòu)計(jì)算的硬件解決方案
- 單機(jī)單卡:一個(gè)主機(jī)內(nèi)安裝上一塊GPU運(yùn)算卡。常見(jiàn)于個(gè)人計(jì)算機(jī)。
- 單機(jī)多卡:一個(gè)主機(jī)內(nèi)安裝上多塊GPU運(yùn)算卡。常見(jiàn)的有:1機(jī)4卡,1機(jī)8卡,甚至有1機(jī)10卡。一般公司都采取這種硬件方案。
- 多機(jī)多卡:多臺(tái)主機(jī)內(nèi)安裝多塊GPU運(yùn)算卡。常見(jiàn)于公司內(nèi)部的計(jì)算集群,一般多機(jī)之間采取Infiniband 來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)的快速通信。
- 定制化:即類(lèi)似于Google的TPU解決方案。常見(jiàn)于“巨無(wú)霸”公司內(nèi)部。
異構(gòu)計(jì)算的通信解決方案
根據(jù)上面的硬件解決方案,我們以ResNet為例:模型的大小為230M,單張圖片運(yùn)算量為11 GFLPOS,Mini-batch假設(shè)為128??梢杂?jì)算出各個(gè)硬件模塊在深度學(xué)習(xí)訓(xùn)練中的耗時(shí)比較:
- GPU:對(duì)于V100,假設(shè)有6 TFLOPS,一次Mini-batch 理論耗時(shí):0.23s。
- PCI-E:常見(jiàn)PCI-E 3.0 * 16,速度為10 GB/s,傳輸一個(gè)模型的理論耗時(shí)為:0.023s。
- 網(wǎng)絡(luò):假設(shè)為10 GB/s的高速網(wǎng)絡(luò),傳輸一個(gè)模型的理論耗時(shí):0.023s。
- Disk:普通的磁盤(pán),我們假設(shè)200M/s的讀取速度,讀取一次Mini-batch所需要的圖片耗時(shí):0.094s。
根據(jù)上面的數(shù)據(jù)結(jié)果,我們似乎可以得出一個(gè)結(jié)論:PCI-E和網(wǎng)絡(luò)的傳輸耗時(shí),相對(duì)于GPU來(lái)說(shuō),整整少了一個(gè)數(shù)量級(jí),所以網(wǎng)絡(luò)通信同步的時(shí)間可以忽略不計(jì)。然而問(wèn)題并沒(méi)有那么簡(jiǎn)單,上面例子中的耗時(shí)只是單個(gè)模型的耗時(shí),但是對(duì)于8卡的集群來(lái)說(shuō),如果使用數(shù)據(jù)并行,每次同步就需要傳輸8份模型,這就導(dǎo)致數(shù)據(jù)傳輸?shù)臅r(shí)間和GPU的計(jì)算時(shí)間“旗鼓相當(dāng)”。這樣的話(huà),GPU就得每訓(xùn)練完一個(gè)Mini-batch,都得等候很久的一段時(shí)間(采取同步更新),這會(huì)浪費(fèi)很多計(jì)算資源。因此,網(wǎng)絡(luò)通信也需要制定對(duì)應(yīng)的解決方案。下面我們以Nvidia NCCL中單機(jī)多卡的通信解決方案為例介紹,而多機(jī)多卡的通信解決方案其實(shí)是類(lèi)似的。
上圖是單機(jī)4卡機(jī)器,在硬件上,兩種不同的通信體系。左邊為普通的PCI-E通信,即4個(gè)GPU之間組成一個(gè)環(huán)狀。右邊為NVLink通信,即兩兩之間相互連接。
常見(jiàn)的通信類(lèi)型如下圖所示:
對(duì)于深度學(xué)習(xí)訓(xùn)練而言,關(guān)鍵的兩種通信類(lèi)型為:Broadcast和Reduce。Broadcast用于Master分發(fā)最新的模型給各個(gè)GPU。Reduce 用于各個(gè)GPU計(jì)算完Mini-batch后,把模型更新值匯總到Master上。以Broadcast為例,最簡(jiǎn)單的通信方式是Master往各個(gè)GPU上發(fā)送數(shù)據(jù),這樣的耗時(shí)就是4次模型傳輸?shù)臅r(shí)間,通信時(shí)間就會(huì)太長(zhǎng),一種簡(jiǎn)單的優(yōu)化方法如下圖所示:
即把所需要傳輸?shù)臄?shù)據(jù)分成若干塊,然后通過(guò)接力的方式逐個(gè)傳遞,每個(gè)GPU都把自己最新的一塊數(shù)據(jù)發(fā)送到下一個(gè)GPU卡上。這種傳輸方式能充分利用硬件層面的通信結(jié)構(gòu),使得需要的耗時(shí)大幅縮減。與此類(lèi)似的,Reduce的通信優(yōu)化也可以采取相同的方式進(jìn)行提速。
美團(tuán)的定制化深度學(xué)習(xí)系統(tǒng)
盡管目前在業(yè)界已經(jīng)推出了很多著名的深度學(xué)習(xí)訓(xùn)練平臺(tái),通用的訓(xùn)練平臺(tái)如TensorFlow、MxNet等等,還有領(lǐng)域?qū)S玫挠?xùn)練平臺(tái),如語(yǔ)音識(shí)別中的Kaldi,但是我們經(jīng)過(guò)調(diào)研后,決定內(nèi)部自主開(kāi)發(fā)一套深度學(xué)習(xí)系統(tǒng),理由如下:
- 通用的訓(xùn)練平臺(tái),缺乏了領(lǐng)域特色的功能。如語(yǔ)音識(shí)別中的特征提取模塊和算法。
- 通用的訓(xùn)練平臺(tái),通常是基于Data-flow Graph,來(lái)對(duì)計(jì)算圖中的每個(gè)operator進(jìn)行建模,所以顆粒度很小,需要調(diào)度的單元多,導(dǎo)任務(wù)調(diào)度復(fù)雜。
- 領(lǐng)域特色的訓(xùn)練平臺(tái),如Kaldi,在神經(jīng)網(wǎng)絡(luò)訓(xùn)練的時(shí)候,性能不足。
- 線(xiàn)上業(yè)務(wù)存在很多特殊性,如果使用TensorFlow之類(lèi)作為訓(xùn)練平臺(tái),不太適合線(xiàn)上業(yè)務(wù)的情景。
NLU線(xiàn)上系統(tǒng)
線(xiàn)上系統(tǒng)的業(yè)務(wù)特點(diǎn)
我們?cè)谠O(shè)計(jì)NLU線(xiàn)上系統(tǒng)時(shí),考慮了NLU業(yè)務(wù)的一些特性。發(fā)現(xiàn)其具備如下的一些特點(diǎn):
- 隨著業(yè)務(wù)和技術(shù)的變化,算法流程也經(jīng)常發(fā)生變化。
- 算法流程是多個(gè)算法串聯(lián)組成的,不單純的只有深度學(xué)習(xí)算法。如分詞等算法就不是DL算法。
- 為了能夠快速響應(yīng)一些緊急問(wèn)題,需要經(jīng)常對(duì)模型進(jìn)行熱更新。
- 更重要的是,我們希望構(gòu)建一個(gè)能以“數(shù)據(jù)驅(qū)動(dòng)”的自動(dòng)迭代閉環(huán)。
業(yè)務(wù)多變
NLU任務(wù)的算法流程是多層級(jí)的,并且業(yè)務(wù)經(jīng)常發(fā)生變化。如下圖所示:
即隨著業(yè)務(wù)要求的變化,NLU系統(tǒng)一開(kāi)始的算法流程,只需要把一個(gè)Query分為兩個(gè)類(lèi),但是到后面,極有可能會(huì)變成需要分為三個(gè)類(lèi)別。
熱更新
根據(jù)業(yè)務(wù)需求,或者為了緊急處理一些特殊問(wèn)題,NLU線(xiàn)上系統(tǒng)經(jīng)常需要做出快速響應(yīng),熱更新算法模型。如最近的熱點(diǎn)詞“skr”,幾乎是一夜之間,突然火爆起來(lái)。如下圖所示的微博,如果不能正確理解“skr”的正確語(yǔ)義,可能就不能準(zhǔn)確理解這條微博想要表達(dá)的意思。
為了避免影響用戶(hù)體驗(yàn),我們可能會(huì)對(duì)NLU系統(tǒng),馬上進(jìn)行熱更新,把新模型緊急進(jìn)行上線(xiàn)。
數(shù)據(jù)驅(qū)動(dòng)的自動(dòng)迭代閉環(huán)
對(duì)于線(xiàn)上系統(tǒng)而言,構(gòu)建如上圖所示的自動(dòng)迭代閉環(huán),能更好地利用業(yè)務(wù)數(shù)據(jù)來(lái)提升服務(wù)質(zhì)量。
NLU線(xiàn)上系統(tǒng)的核心設(shè)計(jì)
算法流程的抽象
為了適應(yīng)線(xiàn)上系統(tǒng)串聯(lián)、多變的算法流程,我們把線(xiàn)上系統(tǒng)的算法進(jìn)行抽象,如下圖所示:
即每一個(gè)算法,都依賴(lài)于若干個(gè)槽位(Slot)和資源(Resource),一旦槽位和資源就位,就會(huì)觸發(fā)對(duì)應(yīng)的算法執(zhí)行。算法的執(zhí)行先通過(guò)算法適配器,來(lái)適配槽位和資源中的數(shù)據(jù),轉(zhuǎn)換成算子的輸入格式。然后算子執(zhí)行算法本身,執(zhí)行完算子后,再經(jīng)過(guò)算法解析器。算法解析器主要用于解析算法執(zhí)行的結(jié)果,觸發(fā)對(duì)應(yīng)的槽位。如根據(jù)算法的結(jié)果,觸發(fā)Top 3的結(jié)果。
多個(gè)算法串聯(lián)起來(lái),就構(gòu)建成如下結(jié)果:
熱更新流程的設(shè)計(jì)
如上圖所示,我們把算法的熱更新流程設(shè)計(jì)如上。初試狀態(tài)為左上角,即多個(gè)Query使用同一份模型數(shù)據(jù)。當(dāng)遇到模型更新的請(qǐng)求后,系統(tǒng)將會(huì)block住新的query(右上角狀態(tài))。然后更新模型完后,新的query使用新的模型,舊query依然使用舊模型(右下角狀態(tài))。最后,當(dāng)使用舊模型的query結(jié)束后,把舊的模型從內(nèi)存中刪除(左下角),然后系統(tǒng)恢復(fù)到初始狀態(tài)。
聲學(xué)模型訓(xùn)練系統(tǒng)
因?yàn)門(mén)ensorFlow等通用深度學(xué)習(xí)訓(xùn)練平臺(tái),缺乏了特征提取等業(yè)務(wù)相關(guān)的領(lǐng)域功能,而Kaldi的聲學(xué)模型訓(xùn)練過(guò)程又太慢。所以美團(tuán)開(kāi)發(fā)了一個(gè)聲學(xué)模型訓(xùn)練系統(tǒng)——Mimir,其具備如下特性:
- 使用比TensorFlow更粗顆粒度的建模單元,使得任務(wù)調(diào)度、優(yōu)化更簡(jiǎn)單方便易行。
- 使用數(shù)據(jù)并行的并行方案,單機(jī)多卡可達(dá)到近線(xiàn)性加速。(采取同步更新策略下,4卡加速比達(dá)到3.8)
- 移植了Kaldi的一些特有的訓(xùn)練算法。
- 速度上為Kaldi的6~7倍。(800個(gè)小時(shí)的訓(xùn)練數(shù)據(jù),單機(jī)單卡的條件下,Kaldi需要6~7天, Mimir只需20個(gè)小時(shí))
- 業(yè)務(wù)上,移植了Kaldi的特征提取等領(lǐng)域的相關(guān)模塊。