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