有哪些深度學習框架可以跑在超算集群上?


GitHub - Microsoft/CNTK: Computational Network Toolkit (CNTK)


PaddlePaddle

不說廢話直接上代碼地址,GitHub 4.7k star: https://github.com/PaddlePaddle/Paddle

我們內部現在就是用PaddlePaddle來跑大部分的深度學習訓練任務的,組裡訓過的大點的模型參數是千億級別大概。PaddlePaddle是2017年ASC17超算大賽總決賽的指定深度學習框架。

開發介面是Python, 系統內部是C++實現的。開發也可以直接使用numpy等,很方便。

支持大規模分散式訓練,支持多GPU訓練,可以在openmpi和最近的kubernetes集群上運行。實現方式可以參考《Large Scale Distributed Deep Networks》這個論文,是目前大部分分散式深度學習訓練的實現思路:


為了完成一個深度學習的訓練任務,集群中會運行多個trainer和parameter server,每個trainer啟動時,會先嘗試從parameter server集群下載最新的參數,然後以mini-batch為單位讀取訓練數據集中的一部分數據(Data shard)。trainer會在訓練過程中持續與parameter server通訊,上傳計算出來的梯度以及下載最新的模型。

每個parameter server保存所有parameter的一個分片(Global model shard),並負責接受所有trainer發送的梯度,完成SGD和優化演算法,然後發送更新後的parameter到每個trainer。

這樣,通過trainer和parameter server的分散式協作,可以完成神經網路的SGD方法的訓練。Paddle可以同時支持同步SGD(synchronize SGD)和非同步SGD(asynchronize SGD)。

在使用同步SGD訓練神經網路時,Paddle使用同步屏障(barrier),使梯度的提交和參數的更新按照順序方式執行。在非同步SGD中,則並不會等待所有trainer提交梯度才更新參數,這樣極大的提高了計算的並行性:parameter server之間不相互依賴,並行的接收梯度和更新參數,parameter server也不會等待trainer全部都提交梯度之後才開始下一步,trainer之間也不會相互依賴,並行的執行模型的訓練。可以看出,雖然非同步SGD方式會提高參數更新並行度, 但是並不能保證參數同步更新,在任意時間某一台parameter server上保存的參數可能比另一台要更新,與同步SGD相比,梯度會有更多的隨機性。

此外PaddlePaddle社區的深度學習書籍,包含了8個章節,介紹了從線性回歸、MNIST、word embedding,、情感分析、語義角色標註、機器翻譯、推薦系統的實現原理和可以直接運行的代碼。http://book.paddlepaddle.org/index.html


部署是一方面,跑的性能是另一方面

我們的經驗是caffe,cntk,tensorflow,mxnet都是正常部署過的

更應該關心的是在超算集群上做分散式訓練的效率如何


關於這問題,我和團隊已經幫不少企業部署了 大集群上(超過8000節點)。我就簡單的回答。拿其中一個用例作為這個回答。關於這企業,為了保障隱私,我就不說了。它的大數據系統使用的是 Cloudera 的 CDH,有14000個節點。項目的最終目的是想要在同個集群上訓練及運行深度學習。使用的深度學習框架是 Deeplearning4j (DL4J)和 DL4J 的系列工具。在我們的建議下,對方採購了40個 NVIDIA 的 TESLA P100 GPU。

項目的開始,對方幫我們預備了(隔離出來)100個節點作為試點。項目分為兩個階段:模型訓練,模型運行(部署生產環境)。

建模(模型訓練)

以下是我們的模型訓練過程:

這裡我們簡單的解釋 Spark 和 CUDA 這兩個重要的組件:

Apache Spark: 作為一種開源的分散式運行時,Spark可以安排多個主機線程。它是Apache軟體基金會去年最受歡迎的項目。Deeplearning4j僅把Spark作為集群的數據訪問層,因為我們的計算需求很大,而Spark目前無法完全滿足我們的速度和容量需求 。Spark基本上就是Hadoop生態系統(HDFS或Hadoop文件系統)的快速ETL(提取、轉換、載入)或數據存儲與訪問工具。我們的目的是利用Hadoop的數據本地化機制,用本地計算來加快計算速度。Spark採用名為分散式彈性數據集(RDD)的構造來實現這種設計。RDD為處理集群上各個分區的數據提供了函數介面。

CUDA: cuDNN的全稱是CUDA深度神經網路庫,由GPU製造商NVIDIA推出。cuDNN是用於實現正向和反向卷積、池化、標準化以及激活層等標準深度學習常式的基元庫。對於深度卷積網路(以及近來的循環網路)而言,cuDNN是速度最快的庫之一。在Facebook的Soumith Chintala開展的圖像處理對標中,cuDNN名列前茅。Deeplearning4j用Java本地介面包裝cuDNN,方便Java用戶使用。

DL4J自帶內置Spark集成,用於處理在集群上開展的分散式神經網路定型。我們採用數據並行來將網路定型向外擴展至多台計算機,每個節點靠一個(或四個)GPU運行。我們用Spark訪問數據。具體方法是在Spark RDD分區(存儲於集群各處的不同數據部分)上進行定型。

我們將分散式文件系統與簡單易用的介面相結合,讓計算能到數據所在地點進行,而不是將數據轉移至計算地點,如此我們既能以便於設置的方式開展分散式定型,又不需要自己從事大量 較為困難的工作。

部署的挑戰

在部署當中,我們也面對到了一些問題,其中一個最大的挑戰是:Java與C++之間的通信:Java不會讓CUDA變慢嗎?

這通常是會的。而在過程當中,我們也有了解決方案。我們通過在堆外進行運算來優化通信。我們採用了JavaCPP和libnd4j。

JavaCPP用Pointer類來實現簡便易行的堆外運算(即數據不會進入垃圾回收器)。如此一來,我們將因為延遲及內存管理負擔降低而獲益;同時垃圾回收器會得到控制,其運行會更有針對性,而這也將帶來益處。Apache Flink、Spark和Hbase等許多分散式系統框架和資料庫都採用了這種方法。

libnd4j:Java不擅長線性代數運算。線性代數運算應當由C++來處理,如此便可以充分利用浮點運算的硬體加速。這也正是libnd4j的用途。 libnd4j 可以參考這裡:deeplearning4j/libnd4j

進行參數平均化的分散式深度學習

分散式神經網路定型的開展方法基本上有兩種:數據並行和模型並行。

數據並行指將一個非常大的數據集細分為多個批次,然後把這些批次分發給在不同硬體上並行運行的模型,同時進行定型。

試想用一套百科全書來定型:每10頁分為一批,將10個批次分發給10個模型進行定型,然後把定型得到的模型參數平均化,形成一個主模型,再將更新後的主模型權重推送至各個分散式模型。定型結束時,將所有的模型參數平均化,產生一個最終模型。

通過DL4J,我們使用了數據並行模式,利用Spark來安排集群中的分散式主機線程:

運行模型

建立了模型,接下來就是如何運行這些模型。在集群上使用 DL4J運行模型很簡單,Hadoop與DL4J都是使用Java實現。通過 kafka 接上數據源與DL4J 即可運行:

希望以上對這個問題有幫助。 想學習深度學習的朋友們加入QQ交流群(查找 deeplearning4j):289058486


浪潮的超算上不是能跑caffe-mpi嗎?


intel caffe + mlsl


推薦閱讀:

中科院說的深度學習指令集diannaoyu到底是什麼?
如何看待Jeff Dean&Hinton投到ICLR17的MoE的工作?
有沒有非線性版本的 矩陣分解,壓縮感知,稀疏編碼?
深度學習在量化投資方面都有哪些可以借鑒應用的地方?如何結合一些策略方法?
在機器學習領域, 不同框架實現的相同演算法,差別能有多大?

TAG:人工智慧 | 超級計算機 | 高性能計算 | 深度學習DeepLearning |