vivo 推薦業務 x DeepRec:全鏈路優化實踐

語言: CN / TW / HK

作者

vivo - 人工智慧推薦團隊:何鑫、李恆、周健、黃金寶

背景

vivo 人工智慧推薦演算法團隊在深耕業務同時,也在積極探索適用於搜尋/廣告/推薦大規模性稀疏性演算法訓練框架。分別探索了 tensornet/XDL/tfra 等框架及元件,這些框架元件在分散式、稀疏性功能上做了擴充套件,能夠彌補 tensorflow 在搜尋/廣告/推薦大規模性稀疏性場景不足,但是在通用性、易用性以及功能特點上,這些框架存在各種不足。

DeepRec 是阿里巴巴集團提供的針對搜尋、推薦、廣告場景模型的訓練/預測引擎,在分散式、圖優化、運算元、Runtime 等方面對稀疏模型進行了深度效能優化,提供了豐富的高維稀疏特徵功能的支援。基於 DeepRec 進行模型迭代不僅能帶來更好的業務效果,同時在 Training/Inference 效能有明顯的效能提升。

作為 DeepRec 最早的一批社群使用者,vivo 在 DeepRec 還是內部專案時,就與 DeepRec 開發者保持密切的合作。經過一年積累與打磨,DeepRec 賦能 vivo 各個業務增長,vivo 也作為 DeepRec 深度使用者,將業務中的需求以及使用中的問題積極回饋到 DeepRec 開源社群。

業務介紹

vivo 人工智慧推薦演算法組的業務包含了資訊流、影片、音樂、廣告等搜尋/廣告/推薦各類業務,基本涵蓋了搜廣推各型別的業務。

為了支撐上述場景的演算法開發上線,vivo 自研了集特徵資料、模型開發、模型推理等流程於一體的推薦服務平臺。通過成熟、規範的推薦元件及服務,該平臺為 vivo 內各推薦業務(廣告、資訊流等)提供一站式的推薦解決方案,便於業務快速構建推薦服務及演算法策略高效迭代。

稀疏模型訓練

3.1 稀疏功能

3.1.1 痛點

在實際業務實踐發現,TensorFlow 原生 Embedding Layer 存在以下問題:

1.靜態 Embedding OOV 問題

在構建 Embedding Layer 的時候,TensorFlow 需要首先構建一個靜態 shape[Vocab_size, Embedding size ] 的 Variable,然後利用 Lookup 的運算元將特徵值的 Embedding 向量查詢出。在增量或者流式訓練中,會出現 OOV 的問題。

2. 靜態 Embedding hash 特徵衝突

為了規避上述的 OOV 問題,通常做法是將特徵值 hash 到一定的範圍,但是又會引入 hash 衝突的問題,導致不同的特徵值共用同一個 Embedding,會造成資訊丟失,對模型訓練是有損的。

3. 靜態 Embedding 記憶體浪費

為了緩解 hash 衝突,通常會設定比真實的特徵值個數 N 大一到兩倍的 hash 範圍,而這又會強行地增加模型的體積。

  1. 低頻特徵冗餘

在引入稀疏特徵時,出現頻次較低以及許久未出現的特徵 ID 對於模型而言是冗餘的。此外,交叉特徵佔據了大量的儲存,可以在不影響訓練效果的前提下過濾掉這些特徵 ID。因此,迫切需求特徵淘汰以及准入機制。

總的來講,TensorFlow 的 Embedding Layer 對真實的業務場景有幾個不太友好的點,第一是可拓展性差,第二是 hash 衝突導致模型訓練有損,第三是無法處理冗餘的稀疏特徵。而 DeepRec 巧妙地解決了上述問題,主要提供了基於 Embedding Variable 的動態 Embeeding 功能和特徵准入/淘汰功能。

3.1.2 Embedding Variable

DeepRec 中的 EmbeddingVariable 以 HashTable 作為內部儲存的基本結構,動態的建立/釋放 Embedding 向量,適配了 Embedding 前向查詢,反向更新等 OP,從而解決了使用者的痛點。

在構建 Embedding Layer 時使用 DeepRec的Embedding Variable。利用 Embedding Variable 具有動態維度的特性,模型訓練對新增的特徵值無感知。此外,由於摒棄了 hash 的操作,訓練的模型也是無損的,同時模型的體積也會縮小。

3.1.3 特徵准入/淘汰

  1. 特徵准入:

DeepRec 提供了基於 BloomFilter 和 Counter 兩種策略的准入機制。特徵准入可以避免模型稀疏特徵的快速增長,拒絕低頻特徵進入模型,影響模型收斂效果。

  1. 特徵淘汰:

DeepRec 支援兩種淘汰策略,一種是按照 global step 進行淘汰,一種是按照 L2 weight 進行淘汰,它們將不符合規則的特徵從模型引數中剔除,保證特徵的有效性。

3.1.4 收益

  1. 靜態 Embedding 升級到動態 Embedding

使用 DeepRec 的動態 Eembedding 替換 TensorFlow 的靜態 Embedding 後,保證所有特徵 Embedding 無衝突,離線auc提升 0.5%,線上點選率提升 1.2%,同時模型體積縮小 20%。

  1. ID 特徵的利用

在使用 TensorFlow 時,vivo 嘗試過對 ID 特徵進行 hash 處理輸入模型,實驗表明這種操作對比基線具有負收益。這是由於 ID 特徵過於稀疏,同時 ID 具有唯一指示性,hash 處理會帶來大量的 Embedding 衝突。基於動態 Embedding,使用 ID 特徵離線 auc 提升 0.4%,線上點選率提升 1%;同時配合 global step 特徵淘汰,離線 auc 提升 0.2%,線上點選率提升 0.5%。

3.2 IO優化

3.2.1 痛點

目前 vivo 內部使用的是 TFRecord 資料格式儲存訓練資料,這種儲存格式存在以下缺陷:

1. 佔用儲存空間大

由於 TFRecord 採用 protocol buffer 結構化資料儲存,儲存不夠緊湊,佔用空間比較大,在訓練時 I/O 開銷也非常大。vivo 嘗試過利用 prebatch 的方式儲存 TFRecord 以節省儲存空間,但是此方案解析相對複雜,I/O 開銷進一步加劇。

2. 非明文儲存

由於 TFRecord 以二進位制格式儲存,無法直接檢視資料內容,存在解析困難、不便進行資料分析的問題。

3.2.2 Parquet Dataset

Parquet 是一種列式儲存的資料格式,能夠節省儲存資源,加快資料讀取速度。DeepRec 的 Parquet Dataset 支援讀取 Parquet 檔案,開箱即用,無需額外安裝第三庫,使用簡單方便。同時,Parquet Dataset 能夠加快資料讀取速度,提高模型訓練的 I/O 效能。

3.2.3 收益

vivo 內部嘗試使用 Parquet Dataset 來替換現有 TFRecord,提高訓練速度 30%,減少樣本儲存成本 38%,降低頻寬成本。同時,vivo 內部支援 hive 查詢 Parquet 檔案,演算法工程師能夠高效快捷地分析樣本資料。

高效能推理框架

在業務逐漸發展過程中,廣告召回量增長 3.5 倍,同時目標預估數增加兩倍,推理計算複雜度增加,超時率超過 5%,嚴重影響線上服務可用性以及業務指標。因此,vivo 嘗試探索升級改造現有推理服務,保證業務可持續發展。vivo 藉助 DeepRec 開源的諸多推理優化功能,在 CPU 推理改造以及 GPU 推理升級方面進行探索,並取得一定收益。

4.1 CPU 推理優化

vivo 直接使用 TensorFlow 提供的 C++ 介面呼叫 Session::Run,無法實現多 Session 併發處理 Request,導致單 Session 無法實現 CPU 的有效利用。如果通過多 Instance 方式(多程序),無法共享底層的 Variable,導致大量使用記憶體,並且每個 Instance 各自載入一遍模型,嚴重影響資源的使用率和模型載入效率。為了提高 CPU 使用率,也嘗試多組 Session Intra/Inter,均會導致 latency升高,服務可用性降低。

基於 ShareNothing 架構的 SessionGroup

DeepRec 提供的 SessionGroup 能夠有效地解決上述問題,其基本架構如下圖所示:

SessionGroup 可配置一組 Session,並且通過 Round Robin (支援使用者自定義策略)方式將使用者請求分發到某一個 Session。SessionGroup 對不同 Session 之間的資源進行隔離,每個 Session 擁有私有的執行緒池,並且支援每個執行緒池繫結底層的 CPU Core(numa-aware),可以最大程度地避免共享資源導致的鎖衝突開銷。SessionGroup 中唯一共享的資源是 Variable,所有 Session 共享底層的 Variable,並且模型載入只需要載入一次。

在使用 SessionGroup 功能後,CPU 使用率低的問題明顯得到緩解,在保證 latency 的前提下極大提高 QPS,單機 QPS 提升高達 80%,單機 CPU 利用率提升 75%。

4.2 GPU 推理優化

經過 SessionGroup 的優化,雖然 CPU 推理效能得到改善,但是超時率依舊無法得到緩解。由於以下幾點原因,vivo 嘗試探索 GPU 推理來優化線上效能。

  1. 多目標模型目標塔數較多

  2. 模型中使用 Attention、LayerNorm、GateNet 等複雜結構

  3. 特徵多,存在大量稀疏特徵

4.2.1 Device Placement Optimization

通常,對於稀疏特徵的處理一般是將其 Embedding 化,由於模型中存在大量的稀疏特徵,因此 vivo 的廣告模型使用大量的 Embedding 運算元。從推理的 timeline 可以看出,Embedding 運算元分散在 timeline 的各個階段,導致大量的 GPU kernel launch 以及資料拷貝,因此圖計算非常耗時。

Device Placement Optimization 完全將 Embedding Layer placed 到 CPU 上,解決Embedding layer 內部存在的 CPU 和 GPU 之間大量資料拷貝問題。

Device Placement Optimization 效能優化明顯,CPU 運算元(主要是 Embedding Layer)的計算集中在 timeline 的最開端,之後 GPU 主要負責網路層的計算。相較於 CPU 推理,Device Placement Optimization P99 降低 35%。

4.2.2 CUDA Multi-Stream 功能

在推理過程中,vivo 發現 GPU 利用率低,GPU 算力浪費。DeepRec 支援使用者使用 multi-stream 功能,多 stream 併發計算,提升 GPU 利用率。多執行緒併發 launch kernel 時,存在較大的鎖開銷,極大影響了 kernel launch 的效率,這裡的鎖與 CUDA Driver 中 Context 相關。因此可以通過使用 MPS/Multi-context 來避免 launch 過程中鎖開銷,從而進一步提升 GPU 有效利用率。

此外,模型中存在大量的 H2D 以及 D2H 的資料拷貝,在原生程式碼中,計算 stream 和拷貝 stream 是獨立的,這會導致 stream 之間存在大量同步開銷,同時對於在 Recv 運算元之後的計算運算元,必須等到 MemCopy 完成之後才能被 launch 執行,MemCopy 和 launch 難以 overlap 執行。基於以上問題,NV 專家計算團隊的同學在 multi-stream 功能基礎上進一步優化,開發了 MergeStream 功能,允許 MemCopy 和計算使用相同的 stream,從而減少上述的同步開銷以及允許 Recv 之後計算運算元 launch 開銷被 overlap。

vivo 在線上推理服務中使用了 multi-stream 功能,P99 降低 18%。更進一步地,在使用 merge stream 功能後,P99 降低 11%。

4.2.3 編譯優化-BladeDISC

BladeDISC 是阿里集團自主研發的、原生支援存在動態尺寸模型的深度學習編譯器。DeepRec 中集成了 BladeDISC,通過使用 BladeDISC 內建的 aStitch 大尺度運算元融合技術對於存在較多訪存密集型運算元的模型有顯著的效果。利用 BladeDISC 對模型進行編譯優化,推理效能得到大幅度提升。

BladeDISC 將大量訪存密集型運算元編譯成一個大的融合運算元,可以大大減少框架排程和 kernel launch 的開銷。區別於其他深度學習編譯器的是,BladeDISC 還會通過優化 GPU 不同層次儲存(特別是 SharedMemory)的使用來提升了訪存操作和 Op 間資料交換的效能。圖中可以看到,綠色是 Blade DISC 優化合並的運算元替代了原圖中大量的運算元。

另外,由於線上模型比較複雜,為了進一步減少編譯耗時、提升部署效率,vivo 啟用了 BladeDISC 的編譯快取功能。開啟此功能時,BladeDISC 僅會在新舊版本模型的 Graph 結構發生改變時觸發編譯,如果新舊模型僅有權重變更則複用之前的編譯結果。經過驗證,編譯快取在保證正確性的同時,幾乎掩蓋了編譯模型的開銷,模型更新速度與之前幾乎相同。在使用 BladeDISC 功能後,線上服務 P99 降低 21%。

4.2.4 總結

DeepRec 提供大量的解決方案可以幫助使用者快速實施 GPU 推理。經過一系列優化,相較於 CPU 推理,GPU 推理 P99 降低 50%,GPU 利用率平均在 60% 以上。此外,線上一張英偉達 T4 顯示卡的推理效能超過兩臺 CPU 機器,節省了大量的機器資源,機器成本降低 60%。

未來規劃

基於 CPU 的分散式非同步訓練存在兩個問題:一是非同步訓練會損失訓練精度,模型難以收斂到最佳;二是隨著模型結構逐漸複雜,訓練效能會急劇下降。未來,vivo 打算嘗試基於 GPU 的同步訓練來加速複雜模型訓練。DeepRec 支援兩種 GPU 同步框架——SparseOperationKit(SOK)和HybridBackend。後續 vivo 將嘗試這兩種 GPU 同步訓練來加速模型訓練。

DeepRec開源地址:https://github.com/alibaba/Deep