weidl x DeepRec:熱門微博推薦框架效能提升實戰

語言: CN / TW / HK

微博推薦團隊:陳雨、韓楠、蔡小娟、高家華

1.專案背景

熱門微博是新浪微博的重要功能之一,包含熱門流、熱點流、頻道流、小視訊後推薦、視訊社群等場景。

推薦首頁 發現頁推薦 沉浸視訊

weidl機器學習框架為熱門微博線上學習提供模型訓練和推理服務,推薦全鏈路中線上推理服務的效能一直是weidl框架優化迭代的重要目標。線上學習系統依託於weidl框架。其服務的吞吐量、平均響應時間、承接上游QPS、機器資源佔用等指標相互制衡,其中weidl框架推理計算的效能至關重要,與推薦服務全鏈路的整體效能指標及成本密切相關。探索引擎中計算圖執行時運算元計算加速的各種特性及優化支援成為本專案主要方向。

DeepRec是阿里巴巴集團提供的針對搜尋、推薦、廣告場景模型的訓練/預測引擎,在分散式、圖優化、運算元、Runtime等方面對稀疏模型進行了深度效能優化,同時提供了稀疏場景下豐富的Embedding相關功能。

本文主要介紹熱門微博推薦的整體架構與DeepRec對熱門推薦框架效能上的提升,並詳細剖析的weidl平臺中使用的DeepRec的重要優化點。

2.熱門微博推薦系統與weidl線上學習平臺

2.1 熱門微博推薦系統整體架構

熱門微博推薦系統可分為前臺業務與weidl線上學習平臺兩個部分。前臺業務為各個業務的介面,負責將推薦結果返回給業務方。線上學習平臺集成了樣本拼接、模型訓練、引數伺服器、模型服務等多個模組,為熱門推薦的多個業務實現了完整的推薦流程,可快速為新業務搭建一套推薦系統。

2.2 weidl線上學習平臺

線上學習平臺是整個系統最核心的部分,主要負責召回、粗排、精排等模組。熱門推薦系統為全鏈路大規模深度模型的線上學習系統,其中召回模組有興趣召回、熱點召回、策略召回、模型召回等多路召回,分別從千萬級物料庫中召回部分候選集,通過每路配額配置,將萬級物料送入粗排模組。粗排階段通過物料特徵離線生成、使用者特徵實時拉取的方式,實現高效能的打分服務,通過粗排排序後,將千級候選集送入精排階段。精排階段模型最為複雜,物料與使用者特徵實時拉取,多場景多目標融合,最終通過規則系統的重排,選出一次曝光的博文,推薦給使用者。

線上學習平臺底層推理計算部分採用bridge模式,支援多個backend,包括DeepRec、TensorFlow、Torch、TensorRT等,同時支援基於CPU與GPU的模型訓練與線上推理。

weidl線上學習平臺

熱門微博推薦系統從2018年開始,經過幾年的升級,在實時性和規模上都有了本質的提升。

2.2.1 實時性

實時性包括模型學習到使用者行為的速度,模型引數的更新應用到線上模型服務的速度。推薦系統的更新速度越快,越能夠反應使用者最近的使用者習慣,越能夠給使用者進行越有時效性的推薦;模型更容易發現最新流行的資料pattern,越能夠讓模型反應找到最新的流行趨勢。工程上主要通過以下幾個方面,實現推薦系統的實時性。

a. 樣本拼接作為模型訓練的起點,一條完整的樣本拼接完成的速度決定了模型學習使用者行為速度的上限,目前熱門推薦樣本拼接視窗為30分鐘,即使用者在客戶端的互動行為在30分鐘內必會生成一條樣本,送入kafka佇列。

b. 模型訓練讀取樣本流kafka,保證kafka無積壓,所以該條樣本會在毫秒級被模型學到,並通過rpc呼叫,更新到訓練的引數伺服器,並將新的模型引數推入kafka佇列。

c. 引數同步服務從模型更新的kafka佇列中讀取資料,將模型最新的引數通過rpc呼叫,傳送給線上服務所用的引數伺服器中,此時從使用者行為到模型更新完成。

d. 模型線上推理服務直連引數伺服器,實時拉取模型最新引數進行打分。除去樣本拼接所需的30分鐘視窗,其餘流程在1分鐘內完成。

2.2.2 大規模深度複雜模型

熱門推薦業務從最初的FM模型,到現在召回階段以雙塔為主,粗排階段以cold dnn為主,精排階段以多場景、多目標的複雜深度模型為主,模型在特徵數量、目標個數、模型結構複雜度上都發生了質的變化,給業務帶來了很大的收益。

精排模型從snr模型迭代到mm模型

粗排雙塔模型迭代到cold dnn模型

模型複雜度的提升給工程架構帶來了不小的壓力,一個multitask模型比一個單目標的dnn模型在算力上是成倍的增加。為了複雜模型的落地,熱門微博推薦團隊探索了多種開源框架,包括TensorRT, XDL,TFRA等,通過測試與原始碼分析,這些框架都在原生Tensorflow基礎上做了不同方向的優化,但效能始終無法滿足要求。同時,我們也通過指令集優化、改進TensorFlow記憶體管理、運算元融合等方式,優化weidl kernel部分效能。

在不斷的優化與開源框架的嘗試中,發現DeepRec框架在效能、易用性、與weidl的相容性上都全面勝出,最終,熱門推薦框架引擎採用DeepRec引擎,提升了訓練與線上推理的新能,同時也給業務帶來了效果上的提升。

3.DeepRec及相關模組優化點剖析

3.1 OneDNN庫加速運算元運算

DeepRec集成了最新版本的開源的跨平臺深度學習效能加速庫oneDNN(oneAPI Deep Neural Network Library),英特爾相關團隊進一步優化將oneDNN 原有的執行緒池統一成DeepRec的Eigen執行緒池,減少了執行緒池切換開銷,避免了不同執行緒池之間競爭而導致的效能下降問題。oneDNN針對主流運算元實現了效能優化,包括MatMul、BiasAdd、LeakyReLU等在稀疏場景中的常見運算元。針對熱門微博的線上模型,效能提升明顯。

在DeepRec中英特爾CESG團隊針對搜尋廣告推薦模型中存在著大量稀疏運算元如Select、DynamicStitch、Transpose、Tile、SparseSegmentMean、Unique、SparseSegmentSum、SparseFillEmptyRows等一系列稀疏運算元進行了深度的優化,下面介紹2個常用稀疏運算元的優化方法。

3.1.1 Select運算元優化

Select運算元實現原理是依據條件來做元素的選擇,此時可採用向量化指令的mask load方式,如圖所示,以減少原先由if條件帶來大量判斷所導致的時間開銷,然後再通過批量選擇提升資料讀寫效率,最終線上測試表明,效能提升顯著。

3.1.2 Transpose運算元優化

同樣,可以使用向量化的unpack和shuffle指令對transpose運算元進行優化,即通過小Block的方式對矩陣進行轉置,最終經線上測試表明,效能提升同樣十分顯著。

3.2 關鍵路徑優先的排程引擎

DeepRec通過對執行引擎以及底層執行緒池的重新設計,達到在不同的場景下,包括trianing和inference,能做到更佳執行效能。保證不同執行緒之間的均衡性,儘量減少執行緒之間的steal,避免加鎖等問題。

Executor的設計需要考慮對記憶體的訪問及其並行實現之間的聯絡,進行多層次任務排程,減少快取缺失和遠端記憶體訪問,充分發揮多核、多節點CPU的並行特性,提升系統的執行效能。線上程池層面,設計Cost-aware執行緒池,結合記憶體感知以及運算元型別等資訊,進行鍼對性優化;在計算圖層面,對張量記憶體的位置進行排程,有利於執行緒池的排程;在運算元生成層面,進行有利於執行緒池任務排程的運算元任務劃分。

DeepRec提供的基於關鍵路徑優化的執行引擎,通過動態採集Session Run情況,統計與計算多組指標,並構建CostModel,計算出一個較優的排程策略。該功能中包含了基於關鍵路徑的排程策略,根據CostModel patching執行細碎運算元的排程策略以及執行緒池Cost-aware排程策略等。

在graph執行過程中,Collector會監測所有運算元執行以及執行緒池情況,包括運算元執行時間,執行緒池pending任務飽和度,以及運算元的前後依賴關係。這些引數會通過CostModel來計算更佳的排程策略。對於一張graph來說,存在一條或者多條關鍵路徑,即從輸入到輸出經過的延時最長的邏輯路徑。graph執行總的時間一定是大於等於關鍵路徑時間。為了讓整個graph執行更快,併發更佳高效 ,在graph執行時應當優先執行關鍵路徑上的節點。

在稀疏模型圖中,可能會存在大量細碎運算元,會帶來大量排程開銷。有些可以通過運算元融合來做優化,運算元融合一般通過graph pattern匹配或者手動指定子圖來確定需要融合的物件,難以覆蓋全部運算元。故而在executor層面,通過trace執行時資料來動態進行批量排程執行,這樣可以減少非必要的細碎運算元排程開銷。

線上程排程層面,目前的執行緒池排程策略比較簡單,如果當前執行執行緒是inter執行緒,優先將task排程到當前執行緒執行,若不是,則排程到一個random執行緒上。執行緒的balance完全由steal機制來保證。在我們的觀察中,發現inter執行緒之間存在大量的steal,這會導致很多鎖以及重複的執行緒排程等開銷。CostModel executor通過採集執行時資料,來確定更佳的執行緒來執行任務,減少大量的steal行為。

在複雜模型上,使用DeepRec的CostModel排程,能夠生成更佳的排程策略,減少排程開銷。在測試的snr模型上平均耗時穩定優化2ms。

3.3 動態感知的記憶體/視訊記憶體分配器

在張量記憶體管理方面,通常存在兩點問題,一個是記憶體碎片過多,另一個是沒有考慮模型結構存在多分支的情況下運算元並行帶來的記憶體增長。其記憶體管理十分粗放,大體上都是執行時依據記憶體請求動態進行記憶體釋放和分配,同時進行一些記憶體池管理。由於無法感知上層應用的分配請求特點,這種記憶體管理存在著記憶體碎片過多的特點。例如在不清楚後續記憶體請求的情況下,由於前期的多次記憶體分配和釋放,會導致後來的大記憶體請求由於記憶體碎片的問題而需要一塊新的記憶體或者OOM。

深度學習模型的記憶體分配由於其應用特點存在著明顯的規律性,訓練時都是以一個個mini-batch的形式訓練,每個mini-batch的分配特徵大體上保持一致,訓練時前向過程一直分配記憶體,較少釋放,而反向過程中會釋放前向計算中的臨時張量,釋放大量記憶體,所以記憶體會週期性呈現先增長後降低的特徵。基於此學習到執行過程中記憶體分配pattern,從而減少記憶體的動態分配以及對記憶體塊做到最佳的複用。同時自適應記憶體分配器也是graph-aware的,這樣使得不同子圖之間存在較小的相互干擾,提高分配效率。自適應記憶體分配器基本架構如下圖所示:

自適應記憶體分配器在訓練過程對於前面的K輪進行一些統計,通過Allocator模組,對記憶體的分配,包括分配的時間點、分配的大小,統計好分配的時間點和大小後,在K輪結束之後會使用啟發式的一些演算法規劃出一個較優的tensor cache planner,planner會建立allocator,並且預分配一些tensor記憶體塊,後續的分配會優先通過此allocator進行分配。

自適應記憶體分配器基本原則是使用盡量少記憶體,同時提高記憶體的複用率。整體來講,自適應記憶體分配器解決了在稀疏場景中記憶體分配上存在的一些問題,主要包括,第一,減少了在稀疏場景中,大量記憶體分配問題,包括小記憶體和大記憶體。譬如小記憶體分配出現在特徵的處理過程中,包括一些特徵的拼接,或者在做一些交叉特徵,這裡會存在大量的小記憶體的分配。同樣在模型訓練也存在很多大的記憶體,包括attention、RNN、或者全連線層,會有一些大記憶體的分配。減少大記憶體的分配,進而也減少了minor pagefault數量。第二,對於tensor能做到更好的複用,減少了總體的記憶體佔用量。

4.DeepRec在業務中取得的收益

4.1 服務效能提升

熱門微博已於9月將weidl的backend全量替換為DeepRec,線上服務與訓練都取得了很大的收益,最明顯的是精排多工模型,圖計算部分DeepRec比原生TensorFlow耗時降低50%,精排階段整體耗時降低20%,單機吞吐量提升30%。

對於雙塔和cold dnn模型,圖計算部分耗時降低20%,粗排階段整體耗時降低10%, 單機吞吐量提升20%,模型訓練模組效能提升20%, 提升了訓練速度並有效的改善了樣本積壓問題。

4.2 效能提升所帶來的其他收益

推薦引擎模組整體耗時減少與吞吐量的提升,減少了推薦在訓練與線上推理上所使用的機器資源,極大的降低了公司成本。

線上推理服務效能提升,使推薦引擎各個模組可以計算更多的候選物料,粗排階段可以計算更多的候選物料,提升物料庫總量與擴大召回條數,精排也由1000條擴到2000條,每個階段候選物料數的增加,都會對整體指標有顯著的提升。

更多關於 DeepRec 訓練/預測引擎相關資訊: http://github.com/alibaba/Deep