基於Spark的異構分佈式深度學習平臺

http://geek.csdn.net/news/detail/58867

導讀:本文介紹百度基於Spark的異構分佈式深度學習系統,把Spark與深度學習平臺PADDLE結合起來解決PADDLE與業務邏輯間的數據通路問題,在此基礎上使用GPU與FPGA異構計算提升每臺機器的數據處理能力,使用YARN對異構資源做分配,支持Multi-Tenancy,讓資源的使用更有效。

深層神經網絡技術最近幾年取得了巨大的突破,特別在語音和圖像識別應用上有質的飛躍,已經被驗證能夠使用到許多業務上。如何大規模分佈式地執行深度學習程序,使其更好地支持不同的業務線成爲當務之急。在過去兩年,百度深度學習實驗室在徐偉的帶領下開發了分佈式深度學習平臺PADDLE(Parallel Asynchronous Distributed Deep Learning),很好地滿足了許多業務需求。但由於PADDLE是獨立的深度學習平臺,不能很好地跟其他業務邏輯結合,導致PADDLE與其他業務邏輯間的數據通路成爲了性能的瓶頸。爲了讓更多的業務使用上深度學習技術,我們開發了Spark on PADDLE平臺,讓PADDLE變成百度Spark生態系統的一個功能模塊。在第一版完成之後,我們發現CPU計算能力已經滿足不了百度巨大的數據量需求,於是我們在Spark on PADDLE的基礎上增加了對異構的支持,充分利用了GPU和FPGA等資源去加速PADDLE上的作業。

深度學習系統PADDLE的設計

PADDLE是一個成熟的分佈式深度學習平臺,廣泛應用於百度的圖像識別、自然語言理解、語音、無人車等領域,其主要的特點是訓練算法高度優化,支持多GPU/CPU訓練,訓練效率高,對稀疏特徵有獨特的優化。

現有的深度學習平臺,一般都是通過單機方式進行訓練,如開源的Caffe平臺也是通過單機多卡的方式進行訓練。但當數據或者模型規模上去以後,要提高訓練效率,必然要進行分佈式訓練,主要有數據並行和模型並行兩種方法。

數據並行是分佈式深度學習用得最多的並行方法。所謂數據並行,就是因爲訓練數據規模非常大,需要把數據拆分,把模型分佈到N個機器訓練。但是因爲最終訓練的是一個模型,同時每個機器只能分配到一部分數據,訓練的同步和收斂性必須得到保證。最經典的做法是在《Parameter Server for Distributed Machine Learning》中提到的用參數服務器(Parameter Server)的方法。具體的想法是用模型參數服務的方法來同步參數的更新,每個參數服務器只負責同步公共參數的一部分。舉個例子來說,如果模型M,被分佈到N個機器上面訓練,每個機器拿到一部分數據圖片描述,假設訓練的參數集合是W,每個機器首先進行本地訓練,假設他們初始化參數都是圖片描述,根據圖片描述,每臺機器都能算出相應的代價函數的梯度,一般按照單機神經網絡反向傳播的方式,每個層都可以梯度來得到參數的修正值,這樣參數就變成圖片描述因爲是多機,每個節點對參數的修正量不同,就會多了一個步驟把各自參數的修正量push給參數服務器,由它統一決策下個訓練循環的修正量,這樣大家的訓練模型就會被統一起來。 
圖片描述

圖1 數據並行

圖1展示了深度學習數據並行的部署架構。一般分爲以下步驟;

  • 訓練數據預處理,把數據切分爲data shards;
  • 每個機器得到同樣的模型定義,並且統一初始化參數;
  • 對於每個訓練循環,每個機器算各自的梯度,並且把梯度修正量push給參數服務器,參數服務器統一計算,並且把下一輪迭代的參數push給本地訓練機器;
  • 不斷循環,直到模型收斂。

參數服務器的更新算法還分爲同步和異步的區別。因爲嚴格同步的方法會讓本地訓練機在每一個訓練迭代都會進行參數的同步更新,這樣在有慢節點的情況下,整個訓練都會被拖慢。異步參數更新的想法是讓參數同步的頻率變長,這樣可以讓本地訓練機迭代好幾個回合以後再進行參數同步,這樣的做法有利有弊,好處是慢節點對這個訓練的影響變小,壞處是每個模型訓練可能會浪費訓練週期,因爲同步以後的修正量可能跟本地訓練機做的修正量有很大的不同。這其中對於同步頻率的把握和異步收斂性的問題都是研究的方向。

模型並行方法如圖2所示,針對參數規模達到單機無法載入的量級或者模型間存在很少連接的區塊的場景,可以考慮做模型並行,但是模型並行通信開銷和同步消耗超過數據並行,效率可能沒有數據並行高。 
圖片描述

圖2 模型並行

PADDLE的設計主要採用了單機做到模型並行、多機做到數據並行的方式,從而達到億級模型規模以上,大規模數據量的分佈式訓練。

PADDLE與業務邏輯結合的痛點

PADDLE是一個獨立的深度學習平臺,不能很好地支持把數據從其他平臺接入的需求。研發人員通常要等上一階段的工作完成產生PADDLE的輸入數據後,把數據先存入HDFS,再讀到PADDLE集羣的本地內存與硬盤,等數據準備好以後再用PADDLE去訓練模型。等模型訓練好後,再把模型存在HDFS裏,讓下一個業務邏輯去讀取。這個過程不僅耗時長,成爲整個計算流程的瓶頸,並且都是重複性的枯燥工作,影響了PADDLE平臺的推廣,讓很多有需要的團隊沒法用上深度學習技術。

爲了解決這個問題,我們設計了Spark on PADDLE架構,把Spark與PADDLE耦合起來,讓PADDLE成爲Spark的一個模塊。如圖3所示,模型訓練可以與前端的功能整合,比如特徵提取通過RDD的形式進行數據傳遞,無需通過HDFS進行數據導流。這樣一來,PADDLE與業務邏輯間的數據通路不再是性能瓶頸。 
圖片描述

圖3 基於百度Spark的通用業務邏輯

Spark on PADDLE架構1.0版

Spark是近幾年快速興起的大數據處理平臺,不僅僅在於它的計算模型比傳統的Hadoop MapReduce要高效很多,同時在於它所帶來的生態系統非常強大。基於Spark計算引擎構建的上層應用如Spark SQL、Spark Streaming、Spark MLlib等,都是很優秀的應用,比傳統應用性能好幾倍,並且更加穩定。同時與Yarn/Mesos的結合讓Spark對計算資源的管理和分配更加靈活。

Spark在百度內部已經廣泛應用,主要用於數據處理和數據分析。但是傳統的數據處理平臺必定會有根據數據訓練模型的機制,廣告系統的CTR預測就是一個例子,對於用戶產生大量的點擊和瀏覽日誌,Spark可以進行處理和清洗。但是對於大規模模型的訓練,Spark MLlib的支持還是有限,特別是對於深度學習的支持,所以需要解決在Spark上支持PADDLE的問題。

對於用戶的應用程序,Spark叫驅動節點(Driver),可以視爲Spark用戶分佈式程序調度和程序流控制的主節點。Spark程序的具體運算都分佈在Worker Node上面的Executor跑。Spark還有一個非常重要的概念叫RDD,這是一個分佈式的分區(partitioned)數據抽象集。Spark所有輸入和輸出數據都是以RDD爲導向的,它不僅描述了數據集的依賴關係,同時還對數據進行了邏輯上的切分,對一個RDD操作一般都是partition來並行的。

圖片描述

圖4 Spark DNN訓練運行構架

Spark DNN訓練運行構架如圖4所示,訓練一般分爲以下5個步驟:

  • DNN 數據預處理和訓練特徵準備

一般這是Spark的強項,不管是流式數據還是已經落盤的數據都通過Spark來進行數據處理,其中包括數據清洗、特徵準備,然後把得到的訓練數據用RDD輸出。

  • 資源申請

Spark訓練任務提交的時候先從Yarn那裏拿到對於DNN訓練任務的節點資源,比如說一個訓練任務需要4個有4 GPU機器的節點。Yarn會對資源做Container式的管理,不管CPU還是GPU對於Yarn來說都是一個虛擬的資源。後文會做具體介紹。

  • 訓練初始化

Driver會根據Yarn分配的資源相應分發模型配置。模型訓練資源庫,並且啓動訓練機和參數服務器,同時初始化模型的初始參數。

  • 模型訓練

訓練的數據會以RDD的方式輸入到訓練機接口,以數據並行的方式進行訓練,並且啓動的訓練機會跟參數服務器通信,完成梯度交換和參數同步,當訓練最大迭代達到或者模型收斂,則訓練終止。

  • 模型預測

模型可以傳入某一個服務器集羣或者以Spark Streaming的方式進行載入並且預測。

在Spark on PADDLE 1.0開發的過程中,我們驗證了Spark確實可以把ETL、訓練數據預處理和深度學習訓練結合起來,同時發現百度內部有很多深度學習需求,需要在1.0的基礎上考慮把Spark on PADDLE平臺化,做到Multi-Tenancy的資源管理、訓練監控、訓練容錯等等。

Spark on PADDLE 架構2.0版

平臺化是Spark on PADDLE 2.0的主要目標。它引入了更多的功能,主要包括在訓練過程中引入了監控機制、容錯機制,加入了ML決策模塊做超參數選擇等。下面是對Spark on PADDLE 2.0設計的分析。

如圖5、圖6所示,客戶可以直接與Spark DNN Driver通信啓動DNN訓練,Spark DNN Driver啓動一個訓練實例(Training Instance),並且透傳訓練數據、訓練網絡配置等信息。一個訓練實例包括了訓練所需的整體服務,包括一組訓練器以及對應的參數服務器。然後有一個訓練Master(Training Master)來管理整個的訓練進程。同時訓練Master管理訓練器和超參數服務器的生存週期和失敗重啓。參數服務器和訓練器會定期給訓練Master發送heartbeat,確保其正常運行。

圖片描述

圖5 Spark on PADDLE 2.0 總體架構

圖片描述

圖6 Spark on PADDLE 2.0 Training Instance架構

訓練過程中的監控機制

當訓練開始以後,用戶會對訓練過程中的一些數據進行監控,包括訓練的每個迭代的loss值、錯誤率、所用的時間以及訓練機和參數服務器的日誌進行監控,我們在實現的過程中會在Worker端用消息傳遞的方式(AKKA)向Driver端彙報訓練的數據。對於整個Spark Job的性能數據會依賴Spark本身提供的監控功能,所有信息都反饋在監控頁面中(Web UI)。

訓練過程中的容錯機制

因爲DNN在訓練過程中,訓練機和參數服務器都是有可能失敗的地方。最簡單的容錯方式是定期對模型的參數和訓練信息做備份,當模型訓練失敗以後,從備份點開始重啓模型訓練就可以。訓練Master會把這些信息收集起來,並且彙報給Spark DNN Driver。對於參數服務器的容錯,可以採取增加冗餘的方法,如果一個參數服務器掛掉,訓練Master會負責重啓相應服務,但是會有一個備份的參數服務器去負責掛掉的參數服務器的參數更新。

超參數選擇

圖片描述

圖7 超參數選擇訓練

超參數是確立模型訓練的基礎,Spark在MLlib中引入了超參數選擇模塊,主要的做法就是通過一定的超參數選擇算法對模型進行並行訓練,最終選擇的超參數將會被用做最終的模型訓練。超參數的選擇對於深度學習很有意義,包括網絡拓撲、參數的衰減率、觸發函數的選擇都是影響深度學習的超參數。圖7顯示了一個大概的超參數選擇流程,模型的特徵選擇到歸化係數(Regulation Parameter)一起配對來訓練一個模型,最終評估模塊選擇最終超參數。在Spark的場景中,DNN Driver端會跟評估端通過RPC通信來決策需要嘗試什麼超參數。評估端邏輯是在Spark DNN Driver依賴的MLApplication服務。如果用戶需要對DNN訓練模型進行超參數選擇,則Spark DNN Driver會根據不同參數配對啓動多個訓練實例,然後根據訓練來是否需要進一步搜索。

Spark異構分佈式計算平臺架構

如上所述,我們已經看到Spark on PADDLE能夠使得傳統的深度學習可以在更大規模的分佈式系統上運行。但是,百度面臨非常現實的問題就是巨量的數據。在百度內部,每天處理的數據量都遠遠超出了傳統平臺的能力,會使用到巨量的模型參數、特徵以及訓練數據。這些巨量數據對分佈式系統的性能和擴展性都提出了更高的要求。一方面,我們希望提供可以比擬傳統MapReduce集羣規模的深度學習計算集羣,可以並行運行大量的深度學習任務;另一方面,每個深度學習模型不可能無限制地切分成更小的單元,因此每個節點的模型處理能力也是至關重要的。

目前以CPU爲主的計算節點受到本身計算能力的限制,遠遠不能滿足計算的需求,因此,我們需要通過更強大的異構計算來加速現在的計算平臺。目前我們的項目主要涉及到兩種計算資源:GPU和FPGA。GPU可以提供強大的計算能力,適用於高密度的計算類型;FPGA有低功耗、高度可定製的特點,適合加速很多特定的動態任務(本項目使用的FPGA硬件加速由百度美國研發中心的計算團隊提供)。

我們的項目正是基於Spark on PADDLE,探索瞭如何有效地把異構資源整合到現在的大規模分佈式系統,以提供高應用性能和易用性爲目標。在滿足前述要求的基礎上,系統需要動態地對GPU/FPGA資源進行管理,進行無縫的調度,正如CPU和Memory等資源的調度一樣。這一功能是通過把資源調度整合到開源的Yarn系統來實現的,而資源隔離方案基於業界流行的Container技術。

同時,我們還需要提供簡單易用的編程接口,以便現有的應用程序可以更快地遷移到我們的系統上來。因爲Spark所有的數據都是基於RDD的,我們創建了一類新的RDD,通過這個RDD,程序可以直接使用到底層的GPU/FPGA來加速相應的計算。我們知道,真正在GPU/FPGA上完成程序的功能,還需要提供Kernels,這裏我們採用了業界最爲流行的標準OpenCL接口,以便於將程序移植到不同的GPU/FPGA。可以看到,一個特定的功能實現需要3個部分:一個Scala Driver,一個C++的Worker以及一個OpenCL Kernel(on GPU/FPGA)。如果常用的功能已經集成在MLlib中,那麼用戶只需要創建自己的Scala Driver,通過新的RDD調用庫裏面已經支持的函數,就可以無縫享受到GPU/FPGA資源的加速。

圖片描述

圖8 Spark異構計算平臺架構

異構系統架構如圖8所示。系統的運行過程如下:

  • 首先用戶應用程序(Scala Driver)會由App Master啓動;
  • 然後用戶應用程序會向Yarn請求其所需的資源,其中GPU、FPGA作爲不同的資源類別,與請求CPU資源方式完全一致;
  • 用戶應用程序取得所有資源,由App Master在相應的App Slave上啓動Container運行用戶程序的一個Scala Worker;
  • 這時,按照程序Scala Worker的需求,如果使用到了新的RDD,便會調用相應的C++的OpenCL程序,如果函數功能是MLlib內嵌的,那麼這部分對用戶也是完全透明的。
  • OpenCL程序啓動後,會把所分配的數據傳輸到GPU或FPGA上,然後在GPU或者FPGA上動態啓動特定的OpenCL Kernel,處理這些已經傳輸過來的數據。
  • OpenCL Kernel計算完成後,數據會自動被拉回到主存,這時OpenCL的程序就可以把結果返回給Scala Worker;
  • 最後所有Scala Worker把結果提交給在App Master上運行的用戶程序Scala Driver。

可以看到,整個流程支持加入了新的GPU/FPGA計算資源,還有需要用戶使用新的RDD。其他方面對用戶程序來說沒有任何額外的改動。

Spark異構平臺性能評估

在異構平臺架構搭建好後,我們首先測試了機器學習底層矩陣運算庫的CPU與GPU性能對比。結果顯示,在執行同一個計算方程時,GPU的加速效果很好,對CPU的加速比大約是30倍。與此同時,百度美國研發中心計算團隊也對Kmeans算法用FPGA進行加速,取得了15到20倍的加速化,而且FPGA能耗只是CPU的20%。在第二個實驗中,我們對比了Spark on PADDLE在訓練ImageNet時的GPU與 CPU加速比,發現使用GPU可以加速30倍,也就是說,在使用異構平臺後我們只用3%的機器資源就可以完成同樣的計算。

在很好地瞭解了異構平臺加速比後,我們也研究了異構平臺的可擴展性。測試結果如圖9所示,基本上隨着GPU資源的增加,計算時間也在線性地降低,表現出很強的可擴展性,可以承受很大的數據量與計算量。 
圖片描述

圖9 Spark異構計算平臺性能數據

總結

本文介紹了百度基於Spark的異構分佈式深度學習系統。把Spark與深度學習平臺PADDLE結合起來解決了PADDLE與業務邏輯間的數據通路問題,使業務方可以很容易地使用深度學習技術。在此基礎上,我們使用GPU與FPGA的異構平臺極大地提升了每臺機器的數據處理能力。在異構平臺上,我們使用YARN對異構資源做分配,以支持Multi-Tenancy,讓資源的使用更有效。下一步工作我們打算把平臺推廣到百度不同的業務平臺,比如語音、百度祕書、百度圖搜、百度無人車等,讓平臺在不同業務上錘鍊。在平臺更成熟後,我們打算把Spark on PADDLE以及異構計算平臺開源,回饋社區。


張偉德:百度美國硅谷研發中心高級架構師,負責大數據、深度學習架構和開發。曾在Yahoo、微軟等公司負責大型分佈式搜索構架設計。

曲寧:百度美國研發中心高級架構師,負責基礎架構以及異構計算平臺架構與開發。CMU大學Cylab研究院研究員。曾在Nvidia以及Google工作。

劉少山:百度美國研發中心高級架構師,從事深度學習以及異構計算平臺架構與開發。曾在LinkedIn、微軟、微軟研究院、INRIA、Intel以及Broadcom工作。

發佈了19 篇原創文章 · 獲贊 60 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章