本論文從分布式系統(tǒng)的角度開(kāi)展針對(duì)當(dāng)前一些機(jī)器學(xué)習(xí)平臺(tái)的研究,綜述了這些平臺(tái)所使用的架構(gòu)設(shè)計(jì),對(duì)這些平臺(tái)在通信和控制上的瓶頸、容錯(cuò)性和開(kāi)發(fā)難度進(jìn)行分析和對(duì)比,并對(duì)分布式機(jī)器學(xué)習(xí)平臺(tái)的未來(lái)研究工作提出了一些建議。文中的工作由MuratDemirbas教授與他的研究生KuoZhang和SalemAlqahtani共同完成。
機(jī)器學(xué)習(xí),特別是深度學(xué)習(xí),已在語(yǔ)音識(shí)別、圖像識(shí)別和自然語(yǔ)言處理以及近期在推薦及搜索引擎等領(lǐng)域上取得了革命性的成功。這些技術(shù)在無(wú)人駕駛、數(shù)字醫(yī)療系統(tǒng)、CRM、廣告、物聯(lián)網(wǎng)等領(lǐng)域具有很好的應(yīng)用前景。當(dāng)然,是資金引領(lǐng)和驅(qū)動(dòng)了技術(shù)的加速推進(jìn),使得我們?cè)诮诳吹搅艘恍C(jī)器學(xué)習(xí)平臺(tái)的推出。
考慮到訓(xùn)練中所涉及的數(shù)據(jù)集和模型的規(guī)模十分龐大,機(jī)器學(xué)習(xí)平臺(tái)通常是分布式平臺(tái),部署了數(shù)十個(gè)乃至數(shù)百個(gè)并行運(yùn)行的計(jì)算節(jié)點(diǎn)對(duì)模型做訓(xùn)練。據(jù)估計(jì)在不遠(yuǎn)的將來(lái),數(shù)據(jù)中心的大多數(shù)任務(wù)都會(huì)是機(jī)器學(xué)習(xí)任務(wù)。
我來(lái)自于分布式系統(tǒng)研究領(lǐng)域,因此我們考慮從分布式系統(tǒng)的角度開(kāi)展針對(duì)這些機(jī)器學(xué)習(xí)平臺(tái)的研究,分析這些平臺(tái)在通信和控制上的瓶頸。我們還考慮了這些平臺(tái)的容錯(cuò)性和易編程性。
我們從設(shè)計(jì)方法上將機(jī)器學(xué)習(xí)平臺(tái)劃分為三個(gè)基本類(lèi)別,分別是:基本數(shù)據(jù)流、參數(shù)-服務(wù)器模型和高級(jí)數(shù)據(jù)流。
下面我們將對(duì)每類(lèi)方法做簡(jiǎn)要介紹,以ApacheSpark為例介紹基本數(shù)據(jù)流,以PMLS(Petuum)為例介紹參數(shù)服務(wù)器模型,而高級(jí)數(shù)據(jù)流則使用TensorFlow和MXNet為例。我們對(duì)比了上述各平臺(tái)的性能并給出了一系列的評(píng)估結(jié)果。要了解詳細(xì)的評(píng)估結(jié)果,可參考我們的論文。遺憾的是,作為一個(gè)小型研究團(tuán)隊(duì),我們無(wú)法開(kāi)展大規(guī)模的評(píng)估。
在本篇博文的最后,我給出了一些結(jié)論性要點(diǎn),并對(duì)分布式機(jī)器學(xué)習(xí)平臺(tái)的未來(lái)研究工作提出了一些建議。對(duì)這些分布式機(jī)器學(xué)習(xí)平臺(tái)已有一定了解的讀者,可以直接跳到本文結(jié)尾。
Spark
在Spark中,計(jì)算被建模為一種有向無(wú)環(huán)圖(DAG),圖中的每個(gè)頂點(diǎn)表示一個(gè)RDD,每條邊表示了RDD上的一個(gè)操作。RDD由一系列被切分的對(duì)象(Partition)組成,這些被切分的對(duì)象在內(nèi)存中存儲(chǔ)并完成計(jì)算,也會(huì)在Shuffle過(guò)程中溢出(Overflow)到磁盤(pán)上
在DAG中,一條從頂點(diǎn)A到B的有向邊E,表示了RDDB是在RDDA上執(zhí)行操作E的結(jié)果。操作分為轉(zhuǎn)換(Transformation)和動(dòng)作(Action)兩類(lèi)。轉(zhuǎn)換操作(例如map、filter和join)應(yīng)用于某個(gè)RDD上,轉(zhuǎn)換操作的輸出是一個(gè)新的RDD。
Spark用戶(hù)將計(jì)算建模為DAG,該DAG表示了在RDD上執(zhí)行的轉(zhuǎn)換和動(dòng)作。DAG進(jìn)而被編譯為多個(gè)Stage。每個(gè)Stage執(zhí)行為一系列并行運(yùn)行的任務(wù)(Task),每個(gè)分區(qū)(Partition)對(duì)應(yīng)于一個(gè)任務(wù)。這里,有限(Narrow)的依賴(lài)關(guān)系將有利于計(jì)算的高效執(zhí)行,而寬泛(Wide)的依賴(lài)關(guān)系則會(huì)引入瓶頸,因?yàn)檫@樣的依賴(lài)關(guān)系引入了通信密集的Shuffle操作,這打斷了操作流。
Spark的分布式執(zhí)行是通過(guò)將DAGStage劃分到不同的計(jì)算節(jié)點(diǎn)實(shí)現(xiàn)的。上圖清晰地展示了這種主機(jī)(master)-工作者(worker)架構(gòu)。驅(qū)動(dòng)器(Driver)包含有兩個(gè)調(diào)度器(Scheduler)組件,即DAG調(diào)度器和任務(wù)調(diào)度器。調(diào)度器對(duì)工作者分配任務(wù),并協(xié)調(diào)工作者。
Spark是為通用數(shù)據(jù)處理而設(shè)計(jì)的,并非專(zhuān)用于機(jī)器學(xué)習(xí)任務(wù)。要在Spark上運(yùn)行機(jī)器學(xué)習(xí)任務(wù),可以使用MLlibforSpark。如果采用基本設(shè)置的Spark,那么模型參數(shù)存儲(chǔ)在驅(qū)動(dòng)器節(jié)點(diǎn)上,在每次迭代后通過(guò)工作者和驅(qū)動(dòng)器間的通信更新參數(shù)。如果是大規(guī)模部署機(jī)器學(xué)習(xí)任務(wù),那么驅(qū)動(dòng)器可能無(wú)法存儲(chǔ)所有的模型參數(shù),這時(shí)就需要使用RDD去容納所有的參數(shù)。這將引入大量的額外開(kāi)銷(xiāo),因?yàn)闉榱巳菁{更新的模型參數(shù),需要在每次迭代中創(chuàng)建新的RDD。更新模型會(huì)涉及在機(jī)器和磁盤(pán)間的數(shù)據(jù)Shuffle,進(jìn)而限制了Spark的擴(kuò)展性。這正是基本數(shù)據(jù)流模型(即DAG)的短板所在。Spark并不能很好地支持機(jī)器學(xué)習(xí)中的迭代運(yùn)算。
PMLS
PMLS是專(zhuān)門(mén)為機(jī)器學(xué)習(xí)任務(wù)而設(shè)計(jì)的。它引入了稱(chēng)為參數(shù)-服務(wù)器(Parameter-Server,PS)的抽象,這種抽象是為了支持迭代密集的訓(xùn)練過(guò)程。
PS(在圖中以綠色方框所示)以分布式key-value數(shù)據(jù)表形式存在于內(nèi)存中,它是可復(fù)制和分片的。每個(gè)節(jié)點(diǎn)(node)都是模型中某個(gè)分片的主節(jié)點(diǎn)(參數(shù)空間),并作為其它分片的二級(jí)節(jié)點(diǎn)或復(fù)制節(jié)點(diǎn)。這樣PS在節(jié)點(diǎn)數(shù)量上的擴(kuò)展性很好。
PS節(jié)點(diǎn)存儲(chǔ)并更新模型參數(shù),并響應(yīng)來(lái)自于工作者的請(qǐng)求。工作者從自己的本地PS拷貝上請(qǐng)求最新的模型參數(shù),并在分配給它們的數(shù)據(jù)集分區(qū)上執(zhí)行計(jì)算。
PMLS也采用了SSP(StaleSynchronousParallelism)模型。相比于BSP(BulkSynchronousParellelism)模型,SSP放寬了每一次迭代結(jié)束時(shí)各個(gè)機(jī)器需做同步的要求。為實(shí)現(xiàn)同步,SSP允許工作者間存在一定程度上的不同步,工業(yè)機(jī)器人維修,并確保了最快的工作者不會(huì)領(lǐng)先最慢的工作者s輪迭代以上。由于處理過(guò)程處于誤差所允許的范圍內(nèi),這種非嚴(yán)格的一致性模型依然適用于機(jī)器學(xué)習(xí)。我曾經(jīng)發(fā)表過(guò)一篇博文專(zhuān)門(mén)介紹這一機(jī)制。
TensorFlow
Google給出了一個(gè)基于分布式機(jī)器學(xué)習(xí)平臺(tái)的參數(shù)服務(wù)器模型,稱(chēng)為DistBelief(此處是我對(duì)DistBelief論文的綜述)。就我所知,大家對(duì)DistBelief的不滿(mǎn)意之處主要在于,它在編寫(xiě)機(jī)器學(xué)習(xí)應(yīng)用時(shí)需要混合一些底層代碼。Google想使其任一雇員都可以在無(wú)需精通分布式執(zhí)行的情況下編寫(xiě)機(jī)器學(xué)習(xí)代碼。正是出于同一原因,Google對(duì)大數(shù)據(jù)處理編寫(xiě)了MapReduce框架。
TensorFlow是一種設(shè)計(jì)用于實(shí)現(xiàn)這一目標(biāo)的平臺(tái)。它采用了一種更高級(jí)的數(shù)據(jù)流處理范式,其中表示計(jì)算的圖不再需要是DAG,圖中可以包括環(huán),并支持可變狀態(tài)。我認(rèn)為T(mén)ensorFlow的設(shè)計(jì)在一定程度上受到了Naiad設(shè)計(jì)理念的影響。
TensorFlow將計(jì)算表示為一個(gè)由節(jié)點(diǎn)和邊組成的有向圖。節(jié)點(diǎn)表示計(jì)算操作或可變狀態(tài)(例如Variable),邊表示節(jié)點(diǎn)間通信的多維數(shù)組,這種多維數(shù)據(jù)稱(chēng)為T(mén)ensor。TensorFlow需要用戶(hù)靜態(tài)地聲明邏輯計(jì)算圖,并通過(guò)將圖重寫(xiě)和劃分到機(jī)器上實(shí)現(xiàn)分布式計(jì)算。需說(shuō)明的是,MXNet,特別是DyNet,使用了一種動(dòng)態(tài)定義的圖。這簡(jiǎn)化了編程,并提高了編程的靈活性。
如上圖所示,在TensorFlow中,分布式機(jī)器學(xué)習(xí)訓(xùn)練使用了參數(shù)-服務(wù)器方法。當(dāng)在TensorFlow中使用PS抽象時(shí),就使用了參數(shù)-服務(wù)器和數(shù)據(jù)并行。TensorFlow聲稱(chēng)可以完成更復(fù)雜的任務(wù),但是這需要用戶(hù)編寫(xiě)代碼以通向那些未探索的領(lǐng)域。
MXNet
MXNet是一個(gè)協(xié)同開(kāi)源項(xiàng)目,源自于在2015年出現(xiàn)的CXXNet、Minverva和Purines等深度學(xué)習(xí)項(xiàng)目。類(lèi)似于TensorFlow,MXNet也是一種數(shù)據(jù)流系統(tǒng),支持具有可變狀態(tài)的有環(huán)計(jì)算圖,并支持使用參數(shù)-服務(wù)器模型的訓(xùn)練計(jì)算。同樣,MXNet也對(duì)多個(gè)CPU/GPU上的數(shù)據(jù)并行提供了很好的支持,并可實(shí)現(xiàn)模型并行。MXNet支持同步的和異步的訓(xùn)練計(jì)算。下圖顯示了MXNet的主要組件。其中,運(yùn)行時(shí)依賴(lài)引擎分析計(jì)算過(guò)程中的依賴(lài)關(guān)系,對(duì)不存在相互依賴(lài)關(guān)系的計(jì)算做并行處理。MXNet在運(yùn)行時(shí)依賴(lài)引擎之上提供了一個(gè)中間層,用于計(jì)算圖和內(nèi)存的優(yōu)化。
MXNet使用檢查點(diǎn)機(jī)制支持基本的容錯(cuò),提供了對(duì)模型的save和load操作。save操作將模型參數(shù)寫(xiě)入到檢查點(diǎn)文件,load操作從檢查點(diǎn)文件中讀取模型參數(shù)。