本論文從分布式系統(tǒng)的角度開展針對(duì)當(dāng)前一些機(jī)器學(xué)習(xí)平臺(tái)的研究,綜述了這些平臺(tái)所使用的架構(gòu)設(shè)計(jì),對(duì)這些平臺(tái)在通信和控制上的瓶頸、容錯(cuò)性和開發(fā)難度進(jìn)行分析和對(duì)比,并對(duì)分布式機(jī)器學(xué)習(xí)平臺(tái)的未來研究工作提出了一些建議。文中的工作由 Murat Demirbas 教授與他的研究生 Kuo Zhang 和 Salem Alqahtani 共同完成。
機(jī)器學(xué)習(xí),特別是深度學(xué)習(xí),已在語(yǔ)音識(shí)別、圖像識(shí)別和自然語(yǔ)言處理以及近期在推薦及搜索引擎等領(lǐng)域上取得了革命性的成功。這些技術(shù)在無人駕駛、數(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)的將來,數(shù)據(jù)中心的大多數(shù)任務(wù)都會(huì)是機(jī)器學(xué)習(xí)任務(wù)。
我來自于分布式系統(tǒng)研究領(lǐng)域,因此我們考慮從分布式系統(tǒng)的角度開展針對(duì)這些機(jī)器學(xué)習(xí)平臺(tái)的研究,分析這些平臺(tái)在通信和控制上的瓶頸。我們還考慮了這些平臺(tái)的容錯(cuò)性和易編程性。
我們從設(shè)計(jì)方法上將機(jī)器學(xué)習(xí)平臺(tái)劃分為三個(gè)基本類別,分別是:基本數(shù)據(jù)流、參數(shù) - 服務(wù)器模型和高級(jí)數(shù)據(jù)流。
下面我們將對(duì)每類方法做簡(jiǎn)要介紹,以 Apache Spark 為例介紹基本數(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ì),我們無法開展大規(guī)模的評(píng)估。
在本篇博文的最后,我給出了一些結(jié)論性要點(diǎn),并對(duì)分布式機(jī)器學(xué)習(xí)平臺(tái)的未來研究工作提出了一些建議。對(duì)這些分布式機(jī)器學(xué)習(xí)平臺(tái)已有一定了解的讀者,可以直接跳到本文結(jié)尾。
Spark
在 Spark 中,計(jì)算被建模為一種有向無環(huán)圖(DAG),圖中的每個(gè)頂點(diǎn)表示一個(gè) RDD,每條邊表示了 RDD 上的一個(gè)操作。RDD 由一系列被切分的對(duì)象(Partition)組成,這些被切分的對(duì)象在內(nèi)存中存儲(chǔ)并完成計(jì)算,也會(huì)在 Shuffle 過程中溢出(Overflow)到磁盤上
在 DAG 中,一條從頂點(diǎn) A 到 B 的有向邊 E,表示了 RDD B 是在 RDD A 上執(zhí)行操作 E 的結(jié)果。操作分為“轉(zhuǎn)換”(Transformation)和“動(dòng)作(Action)”兩類。轉(zhuǎn)換操作(例如 map、filter 和 join)應(yīng)用于某個(gè) RDD 上,轉(zhuǎn)換操作的輸出是一個(gè)新的 RDD。
Spark 用戶將計(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)的依賴關(guān)系將有利于計(jì)算的高效執(zhí)行,而寬泛(Wide)的依賴關(guān)系則會(huì)引入瓶頸,因?yàn)檫@樣的依賴關(guān)系引入了通信密集的 Shuffle 操作,這打斷了操作流 。
Spark 的分布式執(zhí)行是通過將 DAG Stage 劃分到不同的計(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ì)的,并非專用于機(jī)器學(xué)習(xí)任務(wù)。要在 Spark 上運(yùn)行機(jī)器學(xué)習(xí)任務(wù),可以使用 MLlib for Spark。如果采用基本設(shè)置的 Spark,那么模型參數(shù)存儲(chǔ)在驅(qū)動(dòng)器節(jié)點(diǎn)上,在每次迭代后通過工作者和驅(qū)動(dòng)器間的通信更新參數(shù)。如果是大規(guī)模部署機(jī)器學(xué)習(xí)任務(wù),那么驅(qū)動(dòng)器可能無法存儲(chǔ)所有的模型參數(shù),這時(shí)就需要使用 RDD 去容納所有的參數(shù)。這將引入大量的額外開銷,因?yàn)闉榱巳菁{更新的模型參數(shù),需要在每次迭代中創(chuàng)建新的 RDD。更新模型會(huì)涉及在機(jī)器和磁盤間的數(shù)據(jù) Shuffle,進(jìn)而限制了 Spark 的擴(kuò)展性。這正是基本數(shù)據(jù)流模型(即 DAG)的短板所在。Spark 并不能很好地支持機(jī)器學(xué)習(xí)中的迭代運(yùn)算。
PMLS
PMLS 是專門為機(jī)器學(xué)習(xí)任務(wù)而設(shè)計(jì)的。它引入了稱為“參數(shù) - 服務(wù)器”(Parameter-Server,PS)的抽象,這種抽象是為了支持迭代密集的訓(xùn)練過程。
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)來自于工作者的請(qǐng)求。工作者從自己的本地 PS 拷貝上請(qǐng)求最新的模型參數(shù),并在分配給它們的數(shù)據(jù)集分區(qū)上執(zhí)行計(jì)算。
PMLS 也采用了 SSP(Stale Synchronous Parallelism)模型。相比于 BSP(Bulk Synchronous Parellelism)模型 ,SSP 放寬了每一次迭代結(jié)束時(shí)各個(gè)機(jī)器需做同步的要求。為實(shí)現(xiàn)同步,SSP 允許工作者間存在一定程度上的不同步,并確保了最快的工作者不會(huì)領(lǐng)先最慢的工作者 s 輪迭代以上。由于處理過程處于誤差所允許的范圍內(nèi),這種非嚴(yán)格的一致性模型依然適用于機(jī)器學(xué)習(xí)。我曾經(jīng)發(fā)表過一篇博文專門介紹這一機(jī)制。
TensorFlow
Google 給出了一個(gè)基于分布式機(jī)器學(xué)習(xí)平臺(tái)的參數(shù)服務(wù)器模型,稱為“DistBelief”(此處是我對(duì) DistBelief 論文的綜述)。就我所知,大家對(duì) DistBelief 的不滿意之處主要在于,它在編寫機(jī)器學(xué)習(xí)應(yīng)用時(shí)需要混合一些底層代碼。Google 想使其任一雇員都可以在無需精通分布式執(zhí)行的情況下編寫機(jī)器學(xué)習(xí)代碼。正是出于同一原因,Google 對(duì)大數(shù)據(jù)處理編寫了 MapReduce 框架。
TensorFlow 是一種設(shè)計(jì)用于實(shí)現(xiàn)這一目標(biāo)的平臺(tái)。它采用了一種更高級(jí)的數(shù)據(jù)流處理范式,其中表示計(jì)算的圖不再需要是 DAG,圖中可以包括環(huán),并支持可變狀態(tài)。我認(rèn)為 TensorFlow 的設(shè)計(jì)在一定程度上受到了 Naiad 設(shè)計(jì)理念的影響。
TensorFlow 將計(jì)算表示為一個(gè)由節(jié)點(diǎn)和邊組成的有向圖。節(jié)點(diǎn)表示計(jì)算操作或可變狀態(tài)(例如 Variable),邊表示節(jié)點(diǎn)間通信的多維數(shù)組,這種多維數(shù)據(jù)稱為“Tensor”。TensorFlow 需要用戶靜態(tài)地聲明邏輯計(jì)算圖,并通過將圖重寫和劃分到機(jī)器上實(shí)現(xiàn)分布式計(jì)算。需說明的是,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 聲稱可以完成更復(fù)雜的任務(wù),但是這需要用戶編寫代碼以通向那些未探索的領(lǐng)域。
MXNet
MXNet 是一個(gè)協(xié)同開源項(xiàng)目,源自于在 2015 年出現(xiàn)的 CXXNet、Minverva 和 Purines 等深度學(xué)習(xí)項(xiàng)目。類似于 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í)依賴引擎分析計(jì)算過程中的依賴關(guān)系,對(duì)不存在相互依賴關(guān)系的計(jì)算做并行處理。MXNet 在運(yùn)行時(shí)依賴引擎之上提供了一個(gè)中間層,用于計(jì)算圖和內(nèi)存的優(yōu)化。
MXNet 使用檢查點(diǎn)機(jī)制支持基本的容錯(cuò),提供了對(duì)模型的 save 和 load 操作。save 操作將模型參數(shù)寫入到檢查點(diǎn)文件,load 操作從檢查點(diǎn)文件中讀取模型參數(shù)。
MXNet 使用描述式編程語(yǔ)言表述計(jì)算為一個(gè)有向圖,也支持使用一些指令式編程去定義 tensor 的計(jì)算和控制流。MXNet 提供了多種語(yǔ)言(例如 C++、Python、R 和 Scala 等)編寫的客戶端 API。與 TensorFlow 一樣,MXNet 的后臺(tái)核心引擎庫(kù)同樣是使用 C++ 編寫的。
部分評(píng)估結(jié)果
在我們的實(shí)驗(yàn)中,使用了 Amazon EC2 m4.xlarge 實(shí)例。每個(gè)實(shí)例具有 4 個(gè)由 Intel Xeon E5-2676 v3 實(shí)現(xiàn)的 vCPU,及 16GB 的內(nèi)存,EBS 帶寬是 750Mbps。我們對(duì)兩種常見的機(jī)器學(xué)習(xí)任務(wù)進(jìn)行了實(shí)驗(yàn),它們分別是二分類邏輯斯蒂回歸和使用多層神經(jīng)網(wǎng)絡(luò)的圖像分類。本文中只給出了部分結(jié)果圖,更多的實(shí)驗(yàn)結(jié)果可參見我們的論文。需指出的是,我們的實(shí)驗(yàn)具有一些局限性。首先,我們使用機(jī)器數(shù)量不大,不能測(cè)試擴(kuò)展性。其次,我們也只使用了 CPU 計(jì)算,并未測(cè)試 GPU 的使用情況。
該圖展示了各個(gè)平臺(tái)對(duì)邏輯斯蒂回歸的計(jì)算速度。PMLS 和 MXNet 是最快的兩個(gè)系統(tǒng),TensorFlow 速度最慢,而 Spark 介于兩者之間。對(duì)此,我們分析認(rèn)為是由多個(gè)原因?qū)е碌摹J紫?,相比?Spark 和 TensorFlow,PMLS 是一個(gè)輕量級(jí)系統(tǒng),它是采用高性能 C++ 編程語(yǔ)言實(shí)現(xiàn)的,而 Spark 是使用運(yùn)行在 JVM 上的 Scala 語(yǔ)言編寫的。其次,PMLS 中包含的抽象較少,而 TensorFlow 中則具有過多的抽象。抽象增加了系統(tǒng)的復(fù)雜度,并導(dǎo)致運(yùn)行時(shí)開銷。
該圖展示了 DNN 在各個(gè)平臺(tái)上的速度。相比于單層神經(jīng)網(wǎng)絡(luò),當(dāng)發(fā)展到兩層神經(jīng)網(wǎng)絡(luò)時(shí),由于需要更多的迭代計(jì)算,Spark 的性能下降。我們將模型參數(shù)存儲(chǔ)在 Spark 的驅(qū)動(dòng)器中,因?yàn)轵?qū)動(dòng)器可以容納這些參數(shù)。但是如果我們使用 RDD 保持參數(shù),并在每次迭代后做更新,結(jié)果可能會(huì)更差。
該圖展示了平臺(tái)的 CPU 占用率。Spark 應(yīng)用看上去具有偏高的 CPU 占用率,這主要來自于序列化的開銷。有些前期工作也指出了同一問題。
結(jié)論及未來的研究方向
機(jī)器學(xué)習(xí)和深度學(xué)習(xí)應(yīng)用是高度可并行的,但是從并發(fā)算法角度看,要做到并不那么容易。可以說,參數(shù) - 服務(wù)器方法最適合于分布式機(jī)器學(xué)習(xí)平臺(tái)的訓(xùn)練任務(wù)。
考慮到瓶頸,網(wǎng)絡(luò)依然是分布式機(jī)器學(xué)習(xí)應(yīng)用的瓶頸。相比于更高級(jí)的通用數(shù)據(jù)流平臺(tái),更重要的是要提出對(duì)數(shù)據(jù)和模型的更好組織和參與機(jī)制。應(yīng)將數(shù)據(jù)和模型視作一等公民。
此外,還有其它一些因素對(duì)平臺(tái)具有微妙的影響。對(duì)于 Spark,CPU 開銷成為比網(wǎng)絡(luò)局限更嚴(yán)重的瓶頸問題。Spark 使用的編程語(yǔ)言是 Scala 等 JVM 語(yǔ)言,這對(duì) Spark 的性能具有顯著的影響。因此存在著對(duì)更好的監(jiān)控工具以及對(duì)分布式機(jī)器學(xué)習(xí)平臺(tái)性能預(yù)測(cè)的需求。近期已經(jīng)出現(xiàn)了一些工具,例如 Ernest 和 CherryPick,它們解決了一些 Spark 數(shù)據(jù)處理應(yīng)用上的問題。
對(duì)于支持機(jī)器學(xué)習(xí)的運(yùn)行時(shí)分布式系統(tǒng),依然存在著一些開放問題,例如資源調(diào)度和運(yùn)行時(shí)性能改進(jìn)??紤]到應(yīng)用的運(yùn)行時(shí)監(jiān)控和性能分析,下一代的分布式機(jī)器學(xué)習(xí)平臺(tái)應(yīng)提供對(duì)運(yùn)行于平臺(tái)上任務(wù)的計(jì)算、內(nèi)存、網(wǎng)絡(luò)資源的運(yùn)行時(shí)彈性配置和調(diào)度等能力。
在編程和軟件工程的支持上,也同樣有一些開放問題。什么是適合機(jī)器學(xué)習(xí)應(yīng)用的分布式編程抽象?這些問題還需要做進(jìn)一步的研究,并對(duì)分布式機(jī)器學(xué)習(xí)應(yīng)用進(jìn)行檢驗(yàn)和驗(yàn)證,例如使用特定問題輸入測(cè)試 DNN。
參考文獻(xiàn)
論文原文:https://www.cse.buffalo.edu/~demirbas/publications/DistMLplat.pdf
Learning Machine Learning: A beginner's journey,https://muratbuffalo.blogspot.com/2016/12/learning-machine-learning-beginners.html
Paper Review. Petuum: A new platform for distributed machine learning on big data,https://muratbuffalo.blogspot.com/2016/04/petuum-new-platform-for-distributed.html
Google DistBelief paper: Large Scale Distributed Deep Networks,https://muratbuffalo.blogspot.com/2017/01/google-distbelief-paper-large-scale.html
Paper summary: Making sense of Performance in Data Analytics Frameworks (NSDI 15),https://muratbuffalo.blogspot.com/2017/05/paper-summary-making-sense-of.html
Naiad: A timely dataflow system,http://muratbuffalo.blogspot.hk/2014/03/naiad-timely-dataflow-system.html
Paper summary: Making sense of Performance in Data Analytics Frameworks (NSDI 15),http://muratbuffalo.blogspot.hk/2017/05/paper-summary-making-sense-of.html
https://spark-summit.org/east-2017/events/ernest-efficient-performance-prediction-for-advanced-analytics-on-apache-spark/
https://blog.acolyer.org/2017/05/04/cherrypick-adaptively-unearthing-the-best-cloud-configurations-for-big-data-analytics/
作者介紹
Murat Demirbas教授供職于 University at Buffalo,SUNY 的計(jì)算機(jī)科學(xué)與技術(shù)系