QQ 瀏覽器首頁的推薦 Feeds 流。業務入口如圖所示:算法
圖 1 QB Feeds 流業務編程
瀏覽器的 Feeds 業務天天的流點擊曝光日誌在百億級;爲了更好的給用戶提供個性化的推薦服務,若是咱們取半個月的數據來訓練推薦模型的話,則咱們會面對一個千億樣本的情況。瀏覽器
圖 2 模型在線表現的時間衰減曲線服務器
此外,對一個訓練好的模型,咱們觀察了模型在線的指標變化,如圖所示。這個圖說明咱們的 Feeds 流業務是一個時效性高度敏感的業務,在線用戶訪問的規律實時在變化,要取得最好的業務效果,咱們必須不斷及時的更新模型。瀏覽器另外一個業務——識花君,須要用百萬級圖片預訓練一個多分類的圖片分類模型,若是採用單機單卡的模式,大約須要半個月才能訓練一個收斂的模型;若是使用 TensorFlow 的分佈式訓練也大概須要一週,有沒有更高效的方法呢?微信
針對這兩個業務場景,接下來咱們作一些技術分析,看看有沒有一些解法。網絡
在能夠低成本得到樣本的場景,好比廣告、Feeds 流的 ctr 預估場景,由於不須要標註咱們就能夠低成本的獲取海量的正負樣本,這就會促使咱們設法從這海量的樣本里學習足夠的知識。架構
什麼樣的算法模型能夠從海量數據裏學習充分的信息呢?這裏從 VC 維理論出發,咱們知道一個模型能夠容納的信息是有限的;下圖歸納了樣本數量、模型規模和模型效果之間的關係,這裏咱們用模型效果來側面反映模型容納的信息量是基於這樣的假設:若是一個模型從一樣規模的數據裏學習到了更多的信息,那麼我認爲它在業務上會體現出更好的效果。這個假設固然還會有很細微的條件,但這裏就不深究了。框架
圖 3 模型信息和樣本、模型規模的關係dom
從該圖咱們能夠直觀得出一個結論,對於能夠輕易獲取海量樣本的場景,咱們須要用足夠大的模型去容納其中的信息。爲避免過於直觀,這裏我且舉一個例子,以一個億級 Feeds 流業務爲例,若是天天用戶點擊超過一億,那麼單天用戶的 pv 可能在 5-10 億甚至更多;若是咱們取半個月的數據來訓練一個 CTR 預估模型,涉及到的樣本量在 200 億左右(不考慮向下負採樣先),而若是咱們的模型參數是樣本的 10 倍的話(這個範圍並不誇張),咱們的模型參數數量在 2000 億,每一個參數用四字節表示,咱們的模型將達到 1TB 左右;而若是咱們用 double 精度則接近 2TB。機器學習
這個量級的模型如何訓練?如何作在線 serving?2000 億的原始樣本如何存放?答案是惟一的:咱們須要一個分佈式系統。
這是另外一種場景,以某圖像分類業務爲例,咱們要將一個標註好的圖像數據集經過模型分類到幾千個類目上。數據集我假設 1000w 張圖片;咋一看,彷佛這個和大數據關係不大,才一千萬而已,但注意這裏是圖片,若是咱們把圖片的每一個像素做爲一個樣原本對待,這個數據就大了;爲何這麼說?由於咱們用 CNN 類的網絡來訓練的時候,圖片原本就是以像素輸入;是的,這裏的大數據其實想表達的是對算力的要求。
若是咱們在單機單卡(GPU)上來訓練這個分類模型(以 resnet-101 爲例),可能須要 2-3 周;真的是「洛陽親友如相問,就說我在跑 training」。對於算法同窗來講,若是咱們要等一個模型結果須要 3 周,這顯然是很讓人沮喪的一件事。那麼咱們有沒有機會把這個時間縮短到天甚至小時級別呢?答案也是同樣的:咱們須要一個分佈式系統。
上面兩個場景也許只是鵝廠衆多業務場景中的一小部分,但我相信是有必定的表明性的。這裏共同的答案是咱們須要一個分佈式系統來應對業務場景帶來的工程挑戰。從機器成本的角度,咱們不太可能去定製能知足需求的單臺機器來解決;從人力成本的角度出發,咱們也不太可能容忍模型訓練速度的超級低效;所以使用相對便宜的機器構建一個面向機器學習需求的分佈式系統是咱們惟一的選擇。
分佈式機器學習系統,顧名思義,和分佈式文件系統、分佈式後臺服務相似,是一個分佈式系統(這彷佛是廢話);再結合機器學習就不同了,這是一個面向機器學習場景的用相對便宜的機器組建的分佈式系統(這仍是廢話)。那麼和傳統的分佈式系統相比,分佈式機器學習系統有哪些獨有的特色呢?作這類系統的開發須要哪些算法知識和工程思惟呢?
和傳統的分佈式系統很大的一個不一樣的地方在於,傳統的分佈式系統是 operation-oriented;以存儲系統爲例,傳統分佈式文件系統是絕對不能接受好比一個數據塊寫錯地方了這樣的事情的。
圖 4 operation-oriented system
與之不一樣的是,若是咱們以 operation-oriented 的要求來應對分佈式機器學習的問題的話,那結果會是至關悲劇的,以咱們目前的算力,咱們可能根本無法在可接受的時間內完成一個大模型的訓練的。然而上帝關上一扇門的時候也許會幫你掀開屋頂;機器學習的模型和算法自己都是有充足的容錯能力的,你丟個樣本,或者丟個梯度基本不影響模型的最終收斂,而這給了分佈式機器學習系統一條出路,我姑且稱爲 convergence-oriented system。
圖 5 convergence-oriented system
如圖 3 所示,convergence-oriented 系統和下山比較相似,下山的路有無數條,中間你走偏了也無所謂,只要你的大方向是往山下便可。
由於機器學習算法自身的特色,分佈式機器學習系統相比於傳統分佈式系統在數據通訊、同步協議、容災等方面都有極大的活動空間,也爲咱們追求極致的性能打下了基礎。對分佈式機器學習系統的通訊、同步協議有興趣的通訊能夠參考以前的拙做 [1] 和 Eric 的相關文章。接下來帶你們遊覽一下應對兩種場景的可用的系統架構!
關於參數服務器,以前的拙做 [1] 已經有較多的論述,這裏再也不詳細展開,僅做簡單介紹,想深刻了解的同窗請根據 [1] 按圖索驥。
圖 6 參數服務器架構示意圖
如圖所示,參數服務器邏輯上分爲 server 和 worker 兩類角色;server 負責存儲模型參數,每一個節點負責一個參數分片;worker 負責根據不一樣的數據分片來計算該數據分片涉及到的參數對應的梯度增量,並回傳給 server 節點以 update 模型。由於數據和模型都是分佈式存儲,架構簡單健壯,理論上該架構能夠支持的模型規模是無限的;可是另外一方面咱們也應該看到,由於每一個數據分片涉及到的參數分片可能分佈在不一樣的機器上,致使咱們每增長一臺機器,網絡的總體傳輸量會有所增長;以下圖所示
圖 7 參數服務通訊示意圖
所以,在參數服務器架構下,相對於算力瓶頸,網絡更容易成爲咱們的瓶頸,而這又該如何解決呢?請繼續往下瀏覽。
對於圖像分類、機器翻譯這類強依賴 GPU 機器的場景,咱們來看看另外一種狀況:
圖 8 使用 GPU 構建的 ps 架構
如圖所示, 若是咱們使用 GPU 搭建一個 PS 集羣,咱們將面臨更爲嚴峻的挑戰;由於 GPU 的運算速度極快,咱們在作參數 reduce 的時候,與 GPU0 的通訊時間將成爲整個系統的 dominant time 而讓系統中的 GPU 愛莫能助。爲此,百度的 SVAIL 團隊 [3] 從高性能計算領域借鑑了 ring-allreduce 思想,構建了分佈式機器學習的 ring-allreduce 架構,以下所示:
圖 9 ring-allreduce 架構示意圖
將 GPU 佈置成環狀如今以有官方組建 NCCL 能夠支持,對 NCCL 原理感興趣的能夠參考 [4] 等相關 paper。
圖 10 使用 NCCL 搭建的多機多卡環
如圖所示, 當咱們使用 NCCL 將多臺 GPU 機器搭建成環狀結構時,咱們能夠看到在換上以此傳輸的話網絡帶寬能夠獲得比較充分的應用。接下來解釋下 allreduce 的概念,通常的 reduce 概念以下
圖 11 reduce 操做語義
而 allreduce 的概念以下
圖 12 allreduce 操做語義
由於上述圖片已經足夠直觀,這裏就很少加解釋了。接下來咱們介紹 ring-allreduce 爲何適合 GPU 集羣數據並行的場景;考慮到中小規模的模型咱們能夠存放在單臺機器上(單卡 or 多卡但不跨機器),每臺機器根據本身的數據分片訓練模型後經過環狀通訊來作 allreduce 操做;這樣的設定下整個系統的網絡通訊量不會隨着機器增長而增長,而僅僅與模型和帶寬有關,相對於參數服務器架構而言,這是極大的提高。詳細的推導過程能夠參考 [5],我就不贅述了。實際的網絡通訊流程以下所示
圖 13 Ring-allreduce 通訊的物理過程
在介紹了參數服務器和 ring-allreduce 兩種不一樣的分佈式機器學習的系統架構之後咱們該如何根據本身的業務場景來合理的選擇架構、算力社保、部署策略呢?請看下節
前兩節介紹的兩種邏輯架構在物理實現的時候能夠有多種選擇,這裏作幾種推演:
僅使用 PS 架構來支持數據並行,以下圖所示
圖 14 單 server 參數服務器架構
這種架構下僅僅支持 worker 對數據進行並行計算,模型存放在集中的 server 節點,和 spark 的架構相似。由於是單節點,因此模型不可能太大,所以這個模型僅僅對照意義多一點,實際上基本不會這麼用。
在實現的時候,將參數服務器的 worker 和 server 兩個角色融爲一爐,在一個進程裏既有承擔 server 角色的線程,又有負責 worker 的線程;由於 worker 以計算爲主,server 以參數存儲爲主,這種融合有必定的合理性,以下圖所示,虛線框表示一個物理進程,一臺機器上能夠部署一個 or 多個這樣的物理進程。
圖 15 P2P 結構的參數服務器
這種架構的不足之處在我看來有兩點:1. 角色耦合,較難根據機器來調配線程比;debug 也相對困難一點;2. 架構耦合,擴展的靈活性較差;調度系統交護模塊、監控模塊的配合、災難恢復都有必定的風險。
與圖 13 不一樣,若是咱們將 worker 和 server 兩個角色實現爲解耦開的兩個獨立進程,在能夠給調度系統流出更多的活動空間。同時對架構的擴展也預留了空間,若是咱們再獨立一個單獨的調度模塊出來,則演變爲下一種架構。
當咱們將 worker 和 server 拆成兩個獨立的模塊,並引入一個 scheduler 模塊,則會造成一個比較經典的三角色分佈式系統架構;worker 和 server 的角色和職責不變,而 scheduler 模塊則有比較多的選擇:1. 只承擔和下層資源調度系統般若(相似 yarn、mesos)的交互;2. 除 1 外,額外增長對 worker、server 心跳監控、流程控制的功能;以下圖所示:
圖 16 帶控制模塊的參數服務器
引入 scheduler 模塊的另外一個好處是給實現模型並行流出了空間,關於模型並行概念的理解,請參考 [1];關於在 scheduler 模塊下如何實現對模型參數的調度以達到模型並行的效果,請參考 [6] 中對 SchMP 編程範式的論述;調度模塊不只有利於實現模型並行訓練範式,還有其餘好處;好比經過針對特定模型參數相關性的理解,對參數訓練過程進行細粒度的調度,能夠進一步加快模型收斂速度,甚至有機會提高模型指標。這塊也是一個很值得探索的方向, 有興趣的同窗能夠進一步參考 [7]。熟悉分佈式系統的同窗可能會擔憂 scheduler 模塊的單點問題,這個經過 raft、zab 等 paxos 協議能夠獲得比較好的解決,無需過於擔憂。
初始的 ring-allreduce 有一個開源版本是 uber 實現的 horovod 框架,經過測試咱們重現了 horovod 論文裏的加速狀況,以下圖所示
圖 17 多機多卡場景下 ring-allreduce 架構加速比對照 TensorFlow 加速比
從該圖能夠看出 ring-allreduce 的加速比和理想加速比的斜率幾乎徹底一致,而 TensorFlow 的加速比則遠低於次;這證實了 ring-allreduce 通訊機制相對於 ps 機制在網絡通訊方面的優點;但與 PS 架構不一樣的是,初始版本的 ring-allreduce 假設模型參數須要單卡能夠存下,另外若是模型中全鏈接層比較多,則全鏈接層的強耦合性結合 allreduce 相似 bsp 的同步機制,仍是會讓網絡通訊時間成爲瓶頸。所以,在 ring-allreduce 環境下,咱們是否能夠作模型分片、同步協議的改造,好比利用 SSP 來替換 BSP,或者利用梯度壓縮來加快 allreduce 進程都是值得探索的方向。
通過大半年的封閉開發,目前無量系統已經支持了 LR、FM、FFM、DNN 的離線訓練和在線實時訓練。支持了 FTRL、SGD、Adam、AmsGrad 等多種優化算法。針對不一樣的優化算法,咱們在梯度壓縮上也作了一些基本的嘗試,如圖所示
圖 18 不一樣優化算法作梯度壓縮後的收斂指標對比
如圖所示,在 LR 算法分佈式訓練過程當中,咱們過濾掉 99% 的梯度,僅傳輸剩下的 1% 的梯度依然能夠達到模型收斂的效果;並且指標可能還略有提高,咱們推測多是大範圍過濾梯度引入了一些 regularition 的做用。
除了常規算法以外,咱們自研了大規模 embeding+DNN 的分佈式訓練支持,如圖所示
圖 19 自研分佈式 DNN 模型
該模型在召回和精排環節均可以應用,目前已經在召回環節灰度。回到最開始的問題,咱們封閉開發無量的一個初衷仍是爲了支持 Feeds 業務精排環節,那麼面對大數據 + 大模型咱們如今是什麼狀況呢?無量支持了千億級特徵空間的稀疏 LR 的分佈式訓練;目前在線已經實際使用到百億特徵,百億樣板,訓練好的模型爲了方便在單機上作 inference,咱們會作一些裁剪;詳細過程我能夠參考我另外一篇分享。
圖 20 在線效果提高比例
使用了基於無量系統訓練的模型以後,Feeds 在線 CTR 和曝光效率都有顯著的提高,如圖所示;相對提高百分比在兩位數,這個提高是在基於 GBDT+ 細粒度特徵的粗排基礎之上的提高,所以這個結果仍是很是符合業務的預期的。
在另外一個方向上,咱們基於 ring-allreduce 的架構,對大數據 + 小模型的 cv 場景已經能夠作到小時級模型輸出;該場景之後會作更深刻的探索。
無量項目是 MIG 移動瀏覽產品部與無線運營部聯合開發的,團隊主要開發成員由大數據中心下的智能應用組、運營部下的計算框架組以及瀏覽器大資訊業務相關同窗構成,主要成員以下:robertyuan、suziliu、clarebu、yancyliu、wahmingchen、burnessduan、binzhu、、williamqin、carbonzhang、janwang、collinhe、joeyzhong、foxchen、brucebian 等。
本篇爲系列分享的第零篇,主要介紹分佈式機器學習框架的背景及可用架構;接下來咱們會從系統總體概況、工程挑戰、算法挑戰、業務應用等角度展開系列分享,敬請期待!
特別感謝瀏覽器和運營部兩位老闆 henrysxu 和 xinliu 的支持,沒有老闆的支持咱們不會有機會去探索分佈式訓練這個領域;感謝 foxchen、taydai、brucebian 的給力支持,使得項目的進展過程當中,資源的支持始終走在開發先列。感謝 rainyu、joeyzhong、janwang 的支持,在過程當中對項目高度關注,常常組織你們討論和勾兌;最後感謝 robertyuan、suziliu、clarebu、yancyliu、wahmingchen、burnessduan、binzhu、hbsun 等同窗的辛苦開發,過程當中有過碰撞,最終時間讓咱們瞭解彼此,共擔重擔!
還有不少同窗在項目上線過程當中提供了極大的幫助,如 larrytu、aiyima、ballwu 等和咱們一塊兒對流程、對參數,可能沒法一一列出,然感激之情,不減毫釐!
引用
[1] 大規模機器學習框架的四重境界
[2] More Effective Distributed ML via a Stale Synchronous Parallel Parameter Server
[3]https://www.sohu.com/a/127596575_494939
[4] Bandwidth Optimal All-reduce Algorithms for Clusters of Workstations
[5]https://www.zhihu.com/question/63219175/answer/206697974
[6] STRADS: A Distributed Framework for Scheduled Model Parallel Machine Learning
[7] Managed Communication and Consistency for Fast Data-Parallel Iterative Analytics