橫向?qū)Ρ热蠓植际綑C(jī)器學(xué)習(xí)平臺:Spark、PMLS、TensorFlow
分布式機(jī)器學(xué)習(xí)是機(jī)器學(xué)習(xí)領(lǐng)域的一大主要研究方向。近日紐約州立大學(xué)布法羅分校計(jì)算機(jī)科學(xué)與工程教授、Petuum Inc. 顧問 Murat Demirbas 和他的兩位學(xué)生一起發(fā)表了一篇對比現(xiàn)有分布式機(jī)器學(xué)習(xí)平臺的論文,對 Spark、PMLS 和 TensorFlow 等平臺的架構(gòu)和性能進(jìn)行了比較和介紹。Murat Demirbas 教授在論文公布后還發(fā)表了一篇解讀博客文章,機(jī)器之心對這篇文章進(jìn)行了編譯介紹,論文原文可訪問:
https://www.cse.buffalo.edu/~demirbas/publications/DistMLplat.pdf
這篇論文調(diào)查了分布式機(jī)器學(xué)習(xí)平臺所用的設(shè)計(jì)方法,并提出了未來的研究方向。我與我的學(xué)生 Kuo Zhang 和 Salem Alqahtani 合作完成了這一工作。我們在 2016 年秋季完成了這篇論文,并且這篇論文還將出現(xiàn)在 ICCCN'17(溫哥華)會(huì)議上。
機(jī)器學(xué)習(xí)(尤其是深度學(xué)習(xí))最近已經(jīng)在語音識別、圖像識別、自然語言處理和推薦/搜索引擎等方面取得了變革性的成功。這些技術(shù)在自動(dòng)駕駛汽車、數(shù)字醫(yī)療系統(tǒng)、CRM、廣告、物聯(lián)網(wǎng)等方面的應(yīng)用非常有前途。當(dāng)然,資本帶領(lǐng)/推動(dòng)著機(jī)器學(xué)習(xí)加速發(fā)展,我們看到近段時(shí)間以來已經(jīng)誕生了很多機(jī)器學(xué)習(xí)平臺。
因?yàn)橛?xùn)練過程涉及到巨大的數(shù)據(jù)集的模型,機(jī)器學(xué)習(xí)平臺往往是分布式的,它們往往會(huì)使用并行的幾十個(gè)或幾百個(gè)工作器(worker)來訓(xùn)練模型。據(jù)估計(jì),在不久的將來,數(shù)據(jù)中心中運(yùn)行的絕大多數(shù)任務(wù)都將會(huì)是機(jī)器學(xué)習(xí)任務(wù)。
我有分布式系統(tǒng)的研究背景,所以我們決定從分布式系統(tǒng)的角度研究這些機(jī)器學(xué)習(xí)平臺并分析其通信和控制局限。我們也調(diào)查了這些平臺的容錯(cuò)能力和編程難度。
我們將這些分布式機(jī)器學(xué)習(xí)平臺歸類為了三大基本設(shè)計(jì)方法:
1. 基本數(shù)據(jù)流(basic dataflow)
2. 參數(shù)服務(wù)器模型(parameter-server model)
3. 先進(jìn)數(shù)據(jù)流(advanced dataflow)
我們對這三種方法進(jìn)行了簡要介紹并舉例進(jìn)行了說明,其中基本數(shù)據(jù)流方法使用了 Apache Spark、參數(shù)服務(wù)器模型使用了 PMLS(Petuum)、先進(jìn)數(shù)據(jù)流模型使用了 TensorFlow 和 MXNet。我們提供了幾個(gè)比較性能的評估結(jié)果。論文里還有更多評估結(jié)果。不幸的是,作為學(xué)術(shù)界的一個(gè)小團(tuán)隊(duì),我們無法進(jìn)行大規(guī)模的評估。
在本文末尾,我給出了對分布式機(jī)器學(xué)習(xí)平臺未來研究工作的總結(jié)和建議。如果你已經(jīng)了解這些分布式機(jī)器學(xué)習(xí)平臺,可以直接跳至末尾查看結(jié)論。
Spark
在 Spark 中,計(jì)算被建模成有向無環(huán)圖(DAG:directed acyclic graph),其中每一個(gè)頂點(diǎn)都代表一個(gè)彈性分布式數(shù)據(jù)集(RDD:Resilient Distributed Dataset),每一條邊都代表對 RDD 的一個(gè)運(yùn)算。RDD 是被分到了不同邏輯分區(qū)的對象的集合,這些邏輯分區(qū)是作為 in-memory 存儲(chǔ)和處理的,帶有到磁盤的 shuffle/overflow。
在一個(gè) DAG 中,從頂點(diǎn) A 到頂點(diǎn) B 的邊 E 表示:RDD B 是在 RDD A 上執(zhí)行運(yùn)算 E 后得到的結(jié)果。運(yùn)算有兩種:變換(transformation)和動(dòng)作(action)。變換(比如:映射、過濾、連接)是指在一個(gè) RDD 上執(zhí)行一種運(yùn)算生成一個(gè)新的 RDD。
Spark 用戶需要將計(jì)算建模為 DAG,從而在 RDD 上進(jìn)行變換或運(yùn)行動(dòng)作。DAG 需要被編譯為 stage。每個(gè) stage 作為一系列并行運(yùn)行的任務(wù)執(zhí)行(每個(gè)分區(qū)執(zhí)行一個(gè)任務(wù))。簡單狹窄的依賴關(guān)系有利于高效執(zhí)行,而寬廣的依賴關(guān)系會(huì)引入瓶頸,因?yàn)樗鼈儠?huì)擾亂流程,而且需要通信密集的 shuffle 運(yùn)算。
Spark 中的分布式執(zhí)行是通過將這種 DAG stage 分割到不同的機(jī)器上執(zhí)行的。這張圖清晰地顯示了這種 master-worker 架構(gòu)。驅(qū)動(dòng)器(driver)包含了任務(wù)和兩個(gè)調(diào)度器(scheduler)組件——DAG 調(diào)度器和任務(wù)調(diào)度器;并且還要將任務(wù)對應(yīng)到工作器。
Spark 是為一般的數(shù)據(jù)處理設(shè)計(jì)的,并不特定于機(jī)器學(xué)習(xí)。但是使用 MLlib for Spark,也可以在 Spark 上進(jìn)行機(jī)器學(xué)習(xí)。在基本的設(shè)置中,Spark 將模型參數(shù)存儲(chǔ)在驅(qū)動(dòng)器節(jié)點(diǎn),工作器與驅(qū)動(dòng)器通信從而在每次迭代后更新這些參數(shù)。對于大規(guī)模部署而言,這些模型參數(shù)可能并不適合驅(qū)動(dòng)器,并且會(huì)作為一個(gè) RDD 而進(jìn)行維護(hù)更新。這會(huì)帶來大量額外開銷,因?yàn)槊看蔚夹枰獎(jiǎng)?chuàng)造一個(gè)新的 RDD 來保存更新后的模型參數(shù)。更新模型涉及到在整個(gè)機(jī)器/磁盤上重排數(shù)據(jù),這就限制了 Spark 的擴(kuò)展性。這是 Spark 的基本數(shù)據(jù)流模型(DAG)的不足之處。Spark 并不能很好地支持機(jī)器學(xué)習(xí)所需的迭代。
PMLS
PMLS 是專為機(jī)器學(xué)習(xí)設(shè)計(jì)的,沒有其它雜亂的歷史。它引入了參數(shù)服務(wù)器(PS: parameter-server)的抽象概念,支持密集迭代的機(jī)器學(xué)習(xí)訓(xùn)練過程。
其中 PS(圖中綠色方框)被用作分布式的內(nèi)存鍵值存儲(chǔ)(distributed in-memory key-value store)。它會(huì)被復(fù)制和共享:每個(gè)節(jié)點(diǎn)都被用作這個(gè)模型(參數(shù)空間)一個(gè)分片的主節(jié)點(diǎn)以及其它分片的次要節(jié)點(diǎn)/副本。因此在節(jié)點(diǎn)數(shù)量方面,PS 可以很好地?cái)U(kuò)展。
PS 節(jié)點(diǎn)會(huì)存儲(chǔ)和更新模型參數(shù)以及響應(yīng)來自工作器的請求。工作器會(huì)請求來自它們的局部 PS 副本的***模型參數(shù),并在分配給它們的數(shù)據(jù)集部分上執(zhí)行計(jì)算。
PMLS 還采用了 SSP(Stale Synchronous Parallelism)模型,這比 BSP(Bulk Synchronous Parellelism)模型更寬松——其中工作器在每次迭代結(jié)束時(shí)同步。SSP 為工作器的同步減少了麻煩,確保最快的工作器不能超過最慢的工作器 s 次迭代。寬松的一致性模型仍然可以用于機(jī)器學(xué)習(xí)訓(xùn)練,因?yàn)檫@個(gè)過程有一定的噪聲容錯(cuò)能力,我在 2016 年 4 月的這篇文章中談過這個(gè)問題:https://muratbuffalo.blogspot.com/2016/04/petuum-new-platform-for-distributed.html
TensorFlow
谷歌有一個(gè)基于參數(shù)服務(wù)器模型的分布式機(jī)器學(xué)習(xí)平臺 DistBelief。參閱我對 DistBelief 論文的評論:https://muratbuffalo.blogspot.com/2017/01/google-distbelief-paper-large-scale.html。在我看來,DistBelief 的主要缺陷是:為了編寫機(jī)器學(xué)習(xí)應(yīng)用,需要操作低級代碼。谷歌想要自己的所有員工無需精通分布式執(zhí)行就能編寫機(jī)器學(xué)習(xí)代碼——基于同樣的理由,谷歌為大數(shù)據(jù)處理編寫了 MapReduce 框架。
所以為了實(shí)現(xiàn)這一目標(biāo),谷歌設(shè)計(jì)了 TensorFlow。TensorFlow 采用了數(shù)據(jù)流范式,但是是一種更高級的版本——其中計(jì)算圖無需是 DAG,而且包含循環(huán)且支持可變狀態(tài)。我認(rèn)為 Naiad 設(shè)計(jì)可能對 TensorFlow 設(shè)計(jì)有所影響。
TensorFlow 使用節(jié)點(diǎn)和邊的有向圖來表示計(jì)算。節(jié)點(diǎn)表示計(jì)算,狀態(tài)可變。而邊則表示多維數(shù)據(jù)數(shù)組(張量),在節(jié)點(diǎn)之間傳輸。TensorFlow 需要用戶靜態(tài)聲明這種符號計(jì)算圖,并對該圖使用復(fù)寫和分區(qū)(rewrite & partitioning)將其分配到機(jī)器上進(jìn)行分布式執(zhí)行。(MXNet,尤其是 DyNet 使用了圖的動(dòng)態(tài)聲明,這改善了編程的難度和靈活性。)
TensorFlow 中的分布式機(jī)器學(xué)習(xí)訓(xùn)練使用了如圖所示的參數(shù)服務(wù)器方法。當(dāng)你在 TensorFlow 中使用 PS 抽象時(shí),你就用到了參數(shù)服務(wù)器和數(shù)據(jù)并行。TensorFlow 讓你還能做更復(fù)雜的事情,但那需要編寫自定義代碼并進(jìn)入全新的疆域。
一些評估結(jié)果
我們的評估使用了 Amazon EC2 m4.xlarge 實(shí)例。每個(gè)實(shí)例包含 4 個(gè)由 Intel Xeon E5-2676 v3 驅(qū)動(dòng)的 vCPU 和 16 GiB RAM。EBS 帶寬為 750Mbps。我們使用了兩個(gè)常見的機(jī)器學(xué)習(xí)任務(wù)進(jìn)行評估:二分類 logistic 回歸和使用多層神經(jīng)網(wǎng)絡(luò)的圖像分類。我在這里僅給出了幾張圖,查看我們的論文可以了解更多實(shí)驗(yàn)。但我們的實(shí)驗(yàn)還有一些局限性:我們使用了少量機(jī)器,不能大規(guī)模測試。我們也限制了 CPU 計(jì)算,沒有測試 GPU。
這幅圖展示了各平臺的 logistic 回歸執(zhí)行速度。Spark 表現(xiàn)不錯(cuò),但落后于 PMLS 和 MXNet。
這幅圖展示了各平臺的深度神經(jīng)網(wǎng)絡(luò)(DNN)執(zhí)行速度。相比于單層的 logistic 回歸,Spark 在兩層神經(jīng)網(wǎng)絡(luò)上有更大的性能損失。這是因?yàn)閮蓪泳W(wǎng)絡(luò)需要更多迭代計(jì)算。在 Spark 中我們將參數(shù)保存在驅(qū)動(dòng)器中,這樣它們可以擬合;如果我們將參數(shù)保存在一個(gè) RDD 中并且在每次迭代后更新,情況還會(huì)變得更加糟糕。
這幅圖給出了各平臺的 CPU 利用率。Spark 應(yīng)用似乎有明顯很高的 CPU 利用率,這主要是因?yàn)樾蛄谢?serialization)的額外開銷。我們更早期的工作已經(jīng)指出了這一問題:
https://muratbuffalo.blogspot.com/2017/05/paper-summary-making-sense-of.html
總結(jié)與未來方向
機(jī)器學(xué)習(xí)/深度學(xué)習(xí)應(yīng)用的并行處理讓人為難,而且從并發(fā)算法(concurrent algorithms)的角度看并不非常有趣??梢韵喈?dāng)肯定地說參數(shù)服務(wù)器方法在分布式機(jī)器學(xué)習(xí)平臺的訓(xùn)練上更好。
至于局限性方面,網(wǎng)絡(luò)仍然是分布式機(jī)器學(xué)習(xí)應(yīng)用的一個(gè)瓶頸。提供更好的數(shù)據(jù)/模型分級比更先進(jìn)的通用數(shù)據(jù)數(shù)據(jù)流平臺更有用;應(yīng)該將數(shù)據(jù)/模型看作頭等公民。
但是,可能會(huì)有一些讓人驚奇和微妙的地方。在 Spark 中,CPU 開銷會(huì)先于網(wǎng)絡(luò)限制變成瓶頸。Spark 使用的編程語言 Scala/JVM 顯著影響了其性能表現(xiàn)。因此分布式機(jī)器學(xué)習(xí)平臺尤其需要更好的監(jiān)控和/或性能預(yù)測工具。最近已經(jīng)有人提出了一些解決 Spark 數(shù)據(jù)處理應(yīng)用的問題的工具,比如 Ernest 和 CherryPick。
在機(jī)器學(xué)習(xí)運(yùn)行時(shí)的分布式系統(tǒng)支持上還有很多懸而未決的問題,比如資源調(diào)度和運(yùn)行時(shí)的性能提升。對應(yīng)用使用運(yùn)行時(shí)監(jiān)控/性能分析,下一代分布式機(jī)器學(xué)習(xí)平臺應(yīng)該會(huì)提供任務(wù)運(yùn)行的計(jì)算、內(nèi)存、網(wǎng)絡(luò)資源的詳細(xì)的運(yùn)行時(shí)彈性配置/調(diào)度。
***,在編程和軟件工程支持方面也有一些待解決的問題。什么樣的(分布式)編程抽象思想適用于機(jī)器學(xué)習(xí)應(yīng)用?另外在分布式機(jī)器學(xué)習(xí)應(yīng)用的檢驗(yàn)和驗(yàn)證(尤其是使用有問題的輸入來測試 DNN)上也還需要更多研究。
原文:http://muratbuffalo.blogspot.jp/2017/07/a-comparison-of-distributed-machine.html
【本文是51CTO專欄機(jī)構(gòu)“機(jī)器之心”的原創(chuàng)譯文,微信公眾號“機(jī)器之心( id: almosthuman2014)”】