自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

外賣廣告大規(guī)模深度學(xué)習(xí)模型工程實(shí)踐

原創(chuàng) 精選
人工智能 新聞
在外賣廣告CTR場景下,深度學(xué)習(xí)模型正在從簡單DNN小模型過渡到千億參數(shù)復(fù)雜模型?;谠摫尘?,本文將重點(diǎn)針對大規(guī)模深度模型在全鏈路帶來的挑戰(zhàn),從在線時(shí)延、離線效率兩個(gè)方面展開,闡述外賣廣告在大規(guī)模深度模型上的工程實(shí)踐經(jīng)驗(yàn),希望能為讀者提供思路上的借鑒。

作者:亞劼 英亮 陳龍等

導(dǎo)語

隨著美團(tuán)外賣業(yè)務(wù)不斷發(fā)展,外賣廣告引擎團(tuán)隊(duì)在多個(gè)領(lǐng)域進(jìn)行了工程上的探索和實(shí)踐,也取得了一些成果。我們將以連載的方式進(jìn)行分享,內(nèi)容主要包括:① 業(yè)務(wù)平臺(tái)化的實(shí)踐;② 大規(guī)模深度學(xué)習(xí)模型工程實(shí)踐;③ 近線計(jì)算的探索與實(shí)踐;④ 大規(guī)模索引構(gòu)建與在線檢索服務(wù)實(shí)踐;⑤ 機(jī)制工程平臺(tái)化實(shí)踐。不久前,我們已發(fā)表過業(yè)務(wù)平臺(tái)化的實(shí)踐(詳情請參閱《??美團(tuán)外賣廣告平臺(tái)化的探索與實(shí)踐??一文)。本文為連載文章的第二篇,我們將重點(diǎn)針對大規(guī)模深度模型在全鏈路層面帶來的挑戰(zhàn),從在線時(shí)延、離線效率兩個(gè)方面進(jìn)行展開,闡述廣告在大規(guī)模深度模型上的工程實(shí)踐,希望能為大家?guī)硪恍椭蛘邌l(fā)。

1 背景

在搜索、推薦、廣告(下簡稱搜推廣)等互聯(lián)網(wǎng)核心業(yè)務(wù)場景下,進(jìn)行數(shù)據(jù)挖掘及興趣建模,為用戶提供優(yōu)質(zhì)的服務(wù),已經(jīng)成為改善用戶體驗(yàn)的關(guān)鍵要素。近幾年,針對搜推廣業(yè)務(wù),深度學(xué)習(xí)模型憑借數(shù)據(jù)紅利和硬件技術(shù)紅利,在業(yè)界得以廣泛落地,同時(shí)在CTR場景,業(yè)界逐步從簡單DNN小模型過渡到數(shù)萬億參數(shù)的Embedding大模型甚至超大模型。外賣廣告業(yè)務(wù)線主要經(jīng)歷了“LR淺層模型(樹模型)” -> “深度學(xué)習(xí)模型” -> “大規(guī)模深度學(xué)習(xí)模型”的演化過程。整個(gè)演化趨勢從以人工特征為主的簡單模型,逐步向以數(shù)據(jù)為核心的復(fù)雜深度學(xué)習(xí)模型進(jìn)行過渡。而大模型的使用,大幅提高了模型的表達(dá)能力,更精準(zhǔn)地實(shí)現(xiàn)了供需側(cè)的匹配,為后續(xù)業(yè)務(wù)發(fā)展提供了更多的可能性。但隨著模型、數(shù)據(jù)規(guī)模的不斷變大,我們發(fā)現(xiàn)效率跟它們存在如下的關(guān)系:圖片根據(jù)上圖所示,在數(shù)據(jù)規(guī)模、模型規(guī)模增長的情況下,所對應(yīng)的“時(shí)長”變得會(huì)越來越長。這個(gè)“時(shí)長”對應(yīng)到離線層面,體現(xiàn)在效率上;對應(yīng)到在線層面,就體現(xiàn)在Latency上。而我們的工作就是圍繞這個(gè)“時(shí)長”的優(yōu)化來開展。

2 分析

相比普通小模型,大模型的核心問題在于:隨著數(shù)據(jù)量、模型規(guī)模增加數(shù)十倍甚至百倍,整體鏈路上的存儲(chǔ)、通信、計(jì)算等都將面臨新的挑戰(zhàn),進(jìn)而影響算法離線的迭代效率。如何突破在線時(shí)延約束等一系列問題?我們先從全鏈路進(jìn)行分析,如下所示:

圖片

“時(shí)長”變長,主要會(huì)體現(xiàn)在以下幾個(gè)方面:

  • 在線時(shí)延:特征層面,在線請求不變的情況下,特征量的增加,帶來的IO、特征計(jì)算耗時(shí)增加等問題尤為突出,需要在特征算子解析編譯、特征抽取內(nèi)部任務(wù)調(diào)度、網(wǎng)絡(luò)I/O傳等方面重塑。在模型層面,模型歷經(jīng)百M(fèi)/G到幾百G的變化,在存儲(chǔ)上帶來了2個(gè)數(shù)量級的上升。此外,單模型的計(jì)算量也出現(xiàn)了數(shù)量級的上漲(FLOPs從百萬到現(xiàn)在千萬),單純的靠CPU,解決不了巨大算力的需求,建設(shè)CPU+GPU+Hierarchical Cache推理架構(gòu)來支撐大規(guī)模深度學(xué)習(xí)推理勢在必行。
  • 離線效率:隨著樣本、特征的數(shù)倍增加,樣本構(gòu)建,模型訓(xùn)練的時(shí)間會(huì)被大大拉長,甚至?xí)兊貌豢山邮?。如何在有限的資源下,解決海量樣本構(gòu)建、模型訓(xùn)練是系統(tǒng)的首要問題。在數(shù)據(jù)層面,業(yè)界一般從兩個(gè)層面去解決,一方面不斷優(yōu)化批處理過程中掣肘的點(diǎn),另一方面把數(shù)據(jù)“化批為流”,由集中式轉(zhuǎn)到分?jǐn)偸?,極大提升數(shù)據(jù)的就緒時(shí)間。在訓(xùn)練層面,通過硬件GPU并結(jié)合架構(gòu)層面的優(yōu)化,來達(dá)到加速目的。其次,算法創(chuàng)新往往都是通過人來驅(qū)動(dòng),新數(shù)據(jù)如何快速匹配模型,新模型如何快速被其他業(yè)務(wù)應(yīng)用,如果說將N個(gè)人放在N條業(yè)務(wù)線上獨(dú)立地做同一個(gè)優(yōu)化,演變成一個(gè)人在一個(gè)業(yè)務(wù)線的優(yōu)化,同時(shí)廣播適配到N個(gè)業(yè)務(wù)線,將會(huì)有N-1個(gè)人力釋放出來做新的創(chuàng)新,這將會(huì)極大地縮短創(chuàng)新的周期,尤其是在整個(gè)模型規(guī)模變大后,不可避免地會(huì)增加人工迭代的成本,實(shí)現(xiàn)從“人找特征/模型” 到“特征/模型找人”的深度轉(zhuǎn)換,減少“重復(fù)創(chuàng)新”,從而達(dá)到模型、數(shù)據(jù)智能化的匹配。
  • Pipeline其他問題:機(jī)器學(xué)習(xí)Pipeline并不是在大規(guī)模深度學(xué)習(xí)模型鏈路里才有,但隨著大模型的鋪開,將會(huì)有新的挑戰(zhàn),比如:① 系統(tǒng)流程如何支持全量、增量上線部署;② 模型的回滾時(shí)長,把事情做正確的時(shí)長,以及事情做錯(cuò)后的恢復(fù)時(shí)長。簡而言之,會(huì)在開發(fā)、測試、部署、監(jiān)測、回滾等方面產(chǎn)生新的訴求。

本文重點(diǎn)從在線時(shí)延(模型推理、特征服務(wù))、離線效率(樣本構(gòu)建、數(shù)據(jù)準(zhǔn)備)等兩個(gè)方面來展開,逐步闡述廣告在大規(guī)模深度模型上的工程實(shí)踐。如何去優(yōu)化“時(shí)長”等相關(guān)問題,我們會(huì)在后續(xù)篇章介進(jìn)行分享,敬請期待。

3 模型推理

在模型推理層面,外賣廣告歷經(jīng)了三個(gè)版本,從1.0時(shí)代,支持小眾規(guī)模的DNN模型為代表,到2.0時(shí)代,高效、低代碼支持多業(yè)務(wù)迭代,再到如今的3.0時(shí)代,逐步面向深度學(xué)習(xí)DNN算力以及大規(guī)模存儲(chǔ)的需求。主要演進(jìn)趨勢如下圖所示:圖片

面向大模型推理場景,3.0架構(gòu)解決的兩個(gè)核心問題是:“存儲(chǔ)問題”和“性能問題”。當(dāng)然,面向N個(gè)百G+模型如何迭代,運(yùn)算量數(shù)十倍增加時(shí)在線穩(wěn)定性如何保障,Pipeline如何加固等等,也是工程面臨的挑戰(zhàn)。下面我們將重點(diǎn)介紹模型推理3.0架構(gòu)是如何通過“分布式”來解決大模型存儲(chǔ)問題,以及如何通過CPU/GPU加速來解決性能、吞吐問題。

3.1 分布式

大模型的參數(shù)主要分為兩部分:Sparse參數(shù)和Dense參數(shù)。

  • Sparse參數(shù):參數(shù)量級很大,一般在億級別,甚至十億/百億級別,這會(huì)導(dǎo)致存儲(chǔ)空間占用較大,通常在百G級別,甚至T級別。其特點(diǎn):①單機(jī)加載困難:在單機(jī)模式下,Sparse參數(shù)需全部加載到機(jī)器內(nèi)存中,導(dǎo)致內(nèi)存嚴(yán)重吃緊,影響穩(wěn)定性和迭代效率;②讀取稀疏:每次推理計(jì)算,只需讀取部分參數(shù),比如User全量參數(shù)在2億級別,但每次推理請求只需讀取1個(gè)User參數(shù)。
  • Dense參數(shù):參數(shù)規(guī)模不大,模型全連接一般在2~3層,參數(shù)量級在百萬/千萬級別。特點(diǎn):① 單機(jī)可加載:Dense參數(shù)占用在幾十兆左右,單機(jī)內(nèi)存可正常加載,比如:輸入層為2000,全連接層為[1024, 512, 256],總參數(shù)為:2000 * 1024 + 1024 * 512 + 512 * 256 + 256 = 2703616,共270萬個(gè)參數(shù),內(nèi)存占用在百兆內(nèi);② 全量讀?。好看瓮评碛?jì)算,需要讀取全量參數(shù)。

因此,解決大模型參數(shù)規(guī)模增長的關(guān)鍵是將Sparse參數(shù)由單機(jī)存儲(chǔ)改造為分布式存儲(chǔ),改造的方式包括兩部分:① 模型網(wǎng)絡(luò)結(jié)構(gòu)轉(zhuǎn)換;② Sparse參數(shù)導(dǎo)出。

3.1.1 模型網(wǎng)絡(luò)結(jié)構(gòu)轉(zhuǎn)換

業(yè)界對于分布式參數(shù)的獲取方式大致分為兩種:外部服務(wù)提前獲取參數(shù)并傳給預(yù)估服務(wù);預(yù)估服務(wù)內(nèi)部通過改造TF(TensorFlow)算子來從分布式存儲(chǔ)獲取參數(shù)。為了減少架構(gòu)改造成本和降低對現(xiàn)有模型結(jié)構(gòu)的侵入性,我們選擇通過改造TF算子的方式來獲取分布式參數(shù)。

正常情況下,TF模型會(huì)使用原生算子進(jìn)行Sparse參數(shù)的讀取,其中核心算子是GatherV2算子,算子的輸入主要有兩部分:① 需要查詢的ID列表;② 存儲(chǔ)Sparse參數(shù)的Embedding表。

算子的作用是從Embedding表中讀取ID列表索引對應(yīng)的Embedding數(shù)據(jù)并返回,本質(zhì)上是一個(gè)Hash查詢的過程。其中,Embedding表存儲(chǔ)的Sparse參數(shù),其在單機(jī)模型中全部存儲(chǔ)在單機(jī)內(nèi)存中。

改造TF算子本質(zhì)上是對模型網(wǎng)絡(luò)結(jié)構(gòu)的改造,改造的核心點(diǎn)主要包括兩部分:① 網(wǎng)絡(luò)圖重構(gòu);② 自定義分布式算子。

1. 網(wǎng)絡(luò)圖重構(gòu):改造模型網(wǎng)絡(luò)結(jié)構(gòu),將原生TF算子替換為自定義分布式算子,同時(shí)進(jìn)行原生Embedding表的固化。

  • 分布式算子替換:遍歷模型網(wǎng)絡(luò),將需要替換的GatherV2算子替換為自定義分布式算子MtGatherV2,同時(shí)修改上下游節(jié)點(diǎn)的Input/Output。
  • 原生Embedding表固化:原生Embedding表固化為占位符,既能保留模型網(wǎng)絡(luò)結(jié)構(gòu)完整,又能避免Sparse參數(shù)對單機(jī)內(nèi)存的占用。

圖片2. 自定義分布式算子:改造根據(jù)ID列表查詢Embedding流程,從本地Embedding表中查詢,改造為從分布式KV中查詢。

  • 請求查詢:將輸入ID進(jìn)行去重以降低查詢量,并通過分片的方式并發(fā)查詢二級緩存(本地Cache + 遠(yuǎn)端KV)獲取Embedding向量。
  • 模型管理:維護(hù)對模型Embedding Meta注冊、卸載流程,以及對Cache的創(chuàng)建、銷毀功能。
  • 模型部署:觸發(fā)模型資源信息的加載,以及對Embedding數(shù)據(jù)并行導(dǎo)入KV的流程。

3.1.2 Sparse參數(shù)導(dǎo)出

  • 分片并行導(dǎo)出:解析模型的Checkpoint文件,獲取Embedding表對應(yīng)的Part信息,并根據(jù)Part進(jìn)行劃分,將每個(gè)Part文件通過多個(gè)Worker節(jié)點(diǎn)并行導(dǎo)出到HDFS上。
  • 導(dǎo)入KV:提前預(yù)分配多個(gè)Bucket,Bucket會(huì)存儲(chǔ)模型版本等信息,便于在線路由查詢。同時(shí)模型的Embedding數(shù)據(jù)也會(huì)存儲(chǔ)到Bucket中,按分片并行方式導(dǎo)入到KV中。

整體流程如下圖所示,我們通過離線分布式模型結(jié)構(gòu)轉(zhuǎn)換、近線數(shù)據(jù)一致性保證、在線熱點(diǎn)數(shù)據(jù)緩存等手段,保障了百G大模型的正常迭代需求。

圖片

可以看到,分布式借助的存儲(chǔ)是外部KV能力,后續(xù)會(huì)替換為更加高效、靈活、易管理的Embedding Service。

3.2 CPU加速

拋開模型本身的優(yōu)化手段外,常見的CPU加速手段主要有兩種:① 指令集優(yōu)化,比如使用AVX2、AVX512指令集;② 使用加速庫(TVM、OpenVINO)。

  1. 指令集優(yōu)化:如果使用TensorFlow模型,在編譯TensorFlow框架代碼時(shí),直接在編譯選項(xiàng)里加入指令集優(yōu)化項(xiàng)即可。實(shí)踐證明引入AVX2、AVX512指令集優(yōu)化效果明顯,在線推理服務(wù)吞吐提升30%+。
  2. 加速庫優(yōu)化:加速庫通過對網(wǎng)絡(luò)模型結(jié)構(gòu)進(jìn)行優(yōu)化融合,以達(dá)到推理加速效果。業(yè)界常用的加速庫有TVM、OpenVINO等,其中TVM支持跨平臺(tái),通用性較好。OpenVINO面向Intel廠商硬件進(jìn)行針對性優(yōu)化,通用性一般,但加速效果較好。

下面,將會(huì)重點(diǎn)介紹我們使用OpenVINO進(jìn)行CPU加速的一些實(shí)踐經(jīng)驗(yàn)。OpenVINO是Intel推出的一套基于深度學(xué)習(xí)的計(jì)算加速優(yōu)化框架,支持機(jī)器學(xué)習(xí)模型的壓縮優(yōu)化、加速計(jì)算等功能。OpenVINO的加速原理簡單概括為兩部分:線性算子融合和數(shù)據(jù)精度校準(zhǔn)。

  1. 線性算子融合:OpenVINO通過模型優(yōu)化器,將模型網(wǎng)絡(luò)中的多層算子進(jìn)行統(tǒng)一線性融合,以降低算子調(diào)度開銷和算子間的數(shù)據(jù)訪存開銷,比如將Conv+BN+Relu三個(gè)算子合并成一個(gè)CBR結(jié)構(gòu)算子。
  2. 數(shù)據(jù)精度校準(zhǔn):模型經(jīng)過離線訓(xùn)練后,由于在推理的過程中不需要反向傳播,完全可以適當(dāng)降低數(shù)據(jù)精度,比如降為FP16或INT8的精度,從而使得內(nèi)存占用更小,推理延遲更低。

CPU加速通常是針對固定Batch的候選隊(duì)列進(jìn)行加速推理,但在搜推廣場景中,候選隊(duì)列往往都是動(dòng)態(tài)的。這就意味著在模型推理之前,需要增加Batch匹配的操作,即將請求的動(dòng)態(tài)Batch候選隊(duì)列映射到一個(gè)離它最近的Batch模型上,但這需構(gòu)建N個(gè)匹配模型,導(dǎo)致N倍的內(nèi)存占用。而當(dāng)前模型體積已達(dá)百G規(guī)模,內(nèi)存嚴(yán)重吃緊。因此,選取合理的網(wǎng)絡(luò)結(jié)構(gòu)用于加速是需要考慮的重點(diǎn)問題。下圖是整體的運(yùn)行架構(gòu):圖片

  1. 網(wǎng)絡(luò)分布:CTR模型網(wǎng)絡(luò)結(jié)構(gòu)整體抽象為三部分:Embedding層、Attention層和MLP層,其中Embedding層用于數(shù)據(jù)獲取,Attention層包含較多邏輯運(yùn)算和輕量級的網(wǎng)絡(luò)計(jì)算,MLP層則為密集網(wǎng)絡(luò)計(jì)算。
  2. 加速網(wǎng)絡(luò)選擇:OpenVINO針對純網(wǎng)絡(luò)計(jì)算的加速效果較好,可以很好地應(yīng)用于MLP層。另外,模型大部分?jǐn)?shù)據(jù)存儲(chǔ)在Embedding層中,MLP層占內(nèi)存只有幾十兆左右。如果針對MLP層網(wǎng)絡(luò)劃分出多個(gè)Batch,模型內(nèi)存占用在優(yōu)化前(Embedding+Attention+MLP)≈ 優(yōu)化后(Embedding+Attention+MLP×Batch個(gè)數(shù)),對于內(nèi)存占用的影響較小。因此,我們最終選取MLP層網(wǎng)絡(luò)作為模型加速網(wǎng)絡(luò)。

目前,基于OpenVINO的CPU加速方案已經(jīng)在生產(chǎn)環(huán)境取得不錯(cuò)效果:CPU與基線持平時(shí),服務(wù)吞吐提升40%,平均時(shí)延下降15%。如果大家想在CPU層面做些加速的話,OpenVINO是個(gè)不錯(cuò)的選擇。

3.3 GPU加速

一方面,隨著業(yè)務(wù)的發(fā)展,業(yè)務(wù)形態(tài)越來越豐富,流量越來越高,模型變寬變深,算力的消耗急劇增加;另一方面,廣告場景主要使用DNN模型,涉及大量稀疏特征Embedding和神經(jīng)網(wǎng)絡(luò)浮點(diǎn)運(yùn)算。作為訪存和計(jì)算密集型的線上服務(wù),在保證可用性的前提下,還要滿足低延遲、高吞吐的要求,對單機(jī)算力也是一種挑戰(zhàn)。這些算力資源需求和空間的矛盾,如果解決不好,會(huì)極大限制業(yè)務(wù)的發(fā)展:在模型加寬加深前,純CPU 推理服務(wù)能夠提供可觀的吞吐,但是在模型加寬加深后,計(jì)算復(fù)雜度上升,為了保證高可用性,需要消耗大量機(jī)器資源,導(dǎo)致大模型無法大規(guī)模應(yīng)用于線上。目前,業(yè)界比較通用的解決辦法是利用GPU來解決這個(gè)問題,GPU本身比較適用于計(jì)算密集型任務(wù)。使用GPU需要解決如下挑戰(zhàn):如何在保證可用性、低延遲的前提下,盡可能做到高吞吐,同時(shí)還需要考慮易用性和通用性。為此,我們也在GPU上做了大量實(shí)踐工作,比如TensorFlow-GPU、TensorFlow-TensorRT、TensorRT等,為了兼顧TF的靈活性以及TensorRT的加速效果,我們采用TensorFlow+TensorRT獨(dú)立兩階段的架構(gòu)設(shè)計(jì)。

3.3.1 加速分析

  • 異構(gòu)計(jì)算:我們的思路跟CPU加速比較一致,200G的深度學(xué)習(xí)CTR模型不能直接全放入到GPU里,訪存密集型算子適用(比如Embedding相關(guān)操作)CPU,計(jì)算密集型算子(比如MLP)適用GPU。
  • GPU使用需要關(guān)注的幾個(gè)點(diǎn):① 內(nèi)存與顯存的頻繁交互;② 時(shí)延與吞吐;③ 擴(kuò)展性與性能優(yōu)化的Trade Off;④ GPU Utilization 。
  • 推理引擎的選擇:業(yè)界常用推理加速引擎有TensorRT、TVM、XLA、ONNXRuntime等,由于TensorRT在算子優(yōu)化相比其他引擎更加深入,同時(shí)可以通過自定義plugin的方式實(shí)現(xiàn)任意算子,具有很強(qiáng)的擴(kuò)展性。而且TensorRT支持常見學(xué)習(xí)平臺(tái)(Caffe、PyTorch、TensorFlow等)的模型,其周邊越來越完善(模型轉(zhuǎn)換工具onnx-tensorrt、性能分析工具nsys等),因此在GPU側(cè)的加速引擎使用TensorRT。
  • 模型分析:CTR模型網(wǎng)絡(luò)結(jié)構(gòu)整體抽象為三部分:Embedding層、Attention層和MLP層,其中Embedding層用于數(shù)據(jù)獲取,適合CPU;Attention層包含較多邏輯運(yùn)算和輕量級的網(wǎng)絡(luò)計(jì)算,MLP層則重網(wǎng)絡(luò)計(jì)算,而這些計(jì)算可以并行進(jìn)行,適合GPU,可以充分利用GPU Core(Cuda Core、Tensor Core),提高并行度。

3.3.2 優(yōu)化目標(biāo)

深度學(xué)習(xí)推理階段對算力和時(shí)延具有很高的要求,如果將訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)直接部署到推理端,很有可能出現(xiàn)算力不足無法運(yùn)行或者推理時(shí)間較長等問題。因此,我們需要對訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)進(jìn)行一定的優(yōu)化。業(yè)界神經(jīng)網(wǎng)絡(luò)模型優(yōu)化的一般思路,可以從模型壓縮、不同網(wǎng)絡(luò)層合并、稀疏化、采用低精度數(shù)據(jù)類型等不同方面進(jìn)行優(yōu)化,甚至還需要根據(jù)硬件特性進(jìn)行針對性優(yōu)化。為此,我們主要圍繞以下兩個(gè)目標(biāo)進(jìn)行優(yōu)化:

  1. 延時(shí)和資源約束下的吞吐:當(dāng)register、Cache等共享資源不需要競爭時(shí),提高并發(fā)可有效提高資源利用率(CPU、GPU等利用率),但隨之可能帶來請求延時(shí)的上漲。由于在線系統(tǒng)的延時(shí)限制非??量蹋圆荒苤煌ㄟ^資源利用率這一指標(biāo)簡單換算在線系統(tǒng)的吞吐上限,需要在延時(shí)約束下結(jié)合資源上限進(jìn)行綜合評估。當(dāng)系統(tǒng)延時(shí)較低,資源(Memory/CPU/GPU等)利用率是制約因素時(shí),可通過模型優(yōu)化降低資源利用率;當(dāng)系統(tǒng)資源利用率均較低,延時(shí)是制約因素時(shí),可通過融合優(yōu)化和引擎優(yōu)化來降低延時(shí)。通過結(jié)合以上各種優(yōu)化手段可有效提升系統(tǒng)服務(wù)的綜合能力,進(jìn)而達(dá)到提升系統(tǒng)吞吐的目的。
  2. 計(jì)算量約束下的計(jì)算密度:CPU/GPU異構(gòu)系統(tǒng)下,模型推理性能主要受數(shù)據(jù)拷貝效率和計(jì)算效率影響,它們分別由訪存密集型算子和計(jì)算密集型算子決定,而數(shù)據(jù)拷貝效率受PCIe數(shù)據(jù)傳輸、CPU/GPU內(nèi)存讀寫等效率的影響,計(jì)算效率受各種計(jì)算單元CPU Core、CUDA Core、Tensor Core等計(jì)算效率的影響。隨著GPU等硬件的快速發(fā)展,計(jì)算密集型算子的處理能力同步快速提高,導(dǎo)致訪存密集型算子阻礙系統(tǒng)服務(wù)能力提升的現(xiàn)象越來越突出,因此減少訪存密集型算子,提升計(jì)算密度對系統(tǒng)服務(wù)能力也變得越來越重要,即在模型計(jì)算量變化不大的情況下,減少數(shù)據(jù)拷貝和kernel launch等。比如通過模型優(yōu)化和融合優(yōu)化來減少算子變換(比如Cast/Unsqueeze/Concat等算子)的使用,使用CUDA Graph減少kernel launch等。

下面將圍繞以上兩個(gè)目標(biāo),具體介紹我們在模型優(yōu)化、融合優(yōu)化引擎優(yōu)化所做的一些工作。

3.3.3 模型優(yōu)化

1. 計(jì)算與傳輸去重:推理時(shí)同一Batch只包含一個(gè)用戶信息,因此在進(jìn)行inference之前可以將用戶信息從Batch Size降為1,真正需要inference時(shí)再進(jìn)行展開,降低數(shù)據(jù)的傳輸拷貝以及重復(fù)計(jì)算開銷。如下圖,inference前可以只查詢一次User類特征信息,并在只有用戶相關(guān)的子網(wǎng)絡(luò)中進(jìn)行裁剪,待需要計(jì)算關(guān)聯(lián)時(shí)再展開。

  • 自動(dòng)化過程:找到重復(fù)計(jì)算的結(jié)點(diǎn)(紅色結(jié)點(diǎn)),如果該結(jié)點(diǎn)的所有葉子結(jié)點(diǎn)都是重復(fù)計(jì)算結(jié)點(diǎn),則該結(jié)點(diǎn)也是重復(fù)計(jì)算結(jié)點(diǎn),由葉子結(jié)點(diǎn)逐層向上查找所有重復(fù)結(jié)點(diǎn),直到結(jié)點(diǎn)遍歷查找完,找到所有紅白結(jié)點(diǎn)的連接線,插入U(xiǎn)ser特征擴(kuò)展結(jié)點(diǎn),對User特征進(jìn)行展開。

圖片

2. 數(shù)據(jù)精度優(yōu)化:由于模型訓(xùn)練時(shí)需要反向傳播更新梯度,對數(shù)據(jù)精度要求較高;而模型推理時(shí),只進(jìn)行前向推理不需要更新梯度,所以在保證效果的前提下,使用FP16或混合精度進(jìn)行優(yōu)化,節(jié)省內(nèi)存空間,減少傳輸開銷,提升推理性能和吞吐。

3. 計(jì)算下推:CTR模型結(jié)構(gòu)主要由Embedding、Attention和MLP三層構(gòu)成,Embedding層偏數(shù)據(jù)獲取,Attention有部分偏邏輯,部分偏計(jì)算,為了充分壓榨GPU的潛力,將CTR模型結(jié)構(gòu)中Attention和MLP大部分計(jì)算邏輯由CPU下沉到GPU進(jìn)行計(jì)算,整體吞吐得到大幅提升。

3.3.4 融合優(yōu)化

在線模型inference時(shí),每一層的運(yùn)算操作都是由GPU完成,實(shí)際上是CPU通過啟動(dòng)不同的CUDA kernel來完成計(jì)算,CUDA kernel計(jì)算張量的速度非???,但是往往大量的時(shí)間是浪費(fèi)在CUDA kernel的啟動(dòng)和對每一層輸入/輸出張量的讀寫操作上,這造成了內(nèi)存帶寬的瓶頸和GPU資源的浪費(fèi)。這里我們將主要介紹TensorRT部分自動(dòng)優(yōu)化以及手工優(yōu)化兩塊工作。1. 自動(dòng)優(yōu)化:TensorRT是一個(gè)高性能的深度學(xué)習(xí)inference優(yōu)化器,可以為深度學(xué)習(xí)應(yīng)用提供低延遲、高吞吐的推理部署。TensorRT可用于對超大規(guī)模模型、嵌入式平臺(tái)或自動(dòng)駕駛平臺(tái)進(jìn)行推理加速。TensorRT現(xiàn)已能支持TensorFlow、Caffe、MXNet、PyTorch等幾乎所有的深度學(xué)習(xí)框架,將TensorRT和NVIDIA的GPU結(jié)合起來,能在幾乎所有的框架中進(jìn)行快速和高效的部署推理。而且有些優(yōu)化不需要用戶過多參與,比如部分Layer Fusion、Kernel Auto-Tuning等。

  • Layer Fusion:TensorRT通過對層間的橫向或縱向合并,使網(wǎng)絡(luò)層的數(shù)量大大減少,簡單說就是通過融合一些計(jì)算op或者去掉一些多余op,來減少數(shù)據(jù)流通次數(shù)、顯存的頻繁使用以及調(diào)度的開銷。比如常見網(wǎng)絡(luò)結(jié)構(gòu)Convolution And ElementWise Operation融合、CBR融合等,下圖是整個(gè)網(wǎng)絡(luò)結(jié)構(gòu)中的部分子圖融合前后結(jié)構(gòu)圖,F(xiàn)usedNewOP在融合過程中可能會(huì)涉及多種Tactic,比如CudnnMLPFC、CudnnMLPMM、CudaMLP等,最終會(huì)根據(jù)時(shí)長選擇一個(gè)最優(yōu)的Tactic作為融合后的結(jié)構(gòu)。通過融合操作,使得網(wǎng)絡(luò)層數(shù)減少、數(shù)據(jù)通道變短;相同結(jié)構(gòu)合并,使數(shù)據(jù)通道變寬;達(dá)到更加高效利用GPU資源的目的。

圖片

  • Kernel Auto-Tuning:網(wǎng)絡(luò)模型在inference時(shí),是調(diào)用GPU的CUDA kernel進(jìn)行計(jì)算。TensorRT可以針對不同的網(wǎng)絡(luò)模型、顯卡結(jié)構(gòu)、SM數(shù)量、內(nèi)核頻率等進(jìn)行CUDA kernel調(diào)整,選擇不同的優(yōu)化策略和計(jì)算方式,尋找適合當(dāng)前的最優(yōu)計(jì)算方式,以保證當(dāng)前模型在特定平臺(tái)上獲得最優(yōu)的性能。上圖是優(yōu)化主要思想,每一個(gè)op會(huì)有多種kernel優(yōu)化策略(cuDNN、cuBLAS等),根據(jù)當(dāng)前架構(gòu)從所有優(yōu)化策略中過濾低效kernel,同時(shí)選擇最優(yōu)kernel,最終形成新的Network。

2. 手工優(yōu)化:眾所周知,GPU適合計(jì)算密集型的算子,對于其他類型算子(輕量級計(jì)算算子,邏輯運(yùn)算算子等)不太友好。使用GPU計(jì)算時(shí),每次運(yùn)算一般要經(jīng)過幾個(gè)流程:CPU在GPU上分配顯存 -> CPU把數(shù)據(jù)發(fā)送給GPU -> CPU啟動(dòng)CUDA kernel -> CPU把數(shù)據(jù)取回 -> CPU釋放GPU顯存。為了減少調(diào)度、kernel launch以及訪存等開銷,需要進(jìn)行網(wǎng)絡(luò)融合。由于CTR大模型結(jié)構(gòu)靈活多變,網(wǎng)絡(luò)融合手段很難統(tǒng)一,只能具體問題具體分析。比如在垂直方向,Cast、Unsqueeze和Less融合,TensorRT內(nèi)部Conv、BN和Relu融合;在水平方向,同維度的輸入算子進(jìn)行融合。為此,我們基于線上實(shí)際業(yè)務(wù)場景,使用NVIDIA相關(guān)性能分析工具(NVIDIA Nsight Systems、NVIDIA Nsight Compute等)進(jìn)行具體問題的分析。把這些性能分析工具集成到線上inference環(huán)境中,獲得inference過程中的GPU Profing文件。通過Profing文件,我們可以清晰的看到inference過程,我們發(fā)現(xiàn)整個(gè)inference中部分算子kernel launch bound現(xiàn)象嚴(yán)重,而且部分算子之間gap間隙較大,存在優(yōu)化空間,如下圖所示:

圖片

為此,基于性能分析工具和轉(zhuǎn)換后的模型對整個(gè)Network分析,找出TensorRT已經(jīng)優(yōu)化的部分,然后對Network中其他可以優(yōu)化的子結(jié)構(gòu)進(jìn)行網(wǎng)絡(luò)融合,同時(shí)還要保證這樣的子結(jié)構(gòu)在整個(gè)Network占有一定的比例,保證融合后計(jì)算密度能夠有一定程度的上升。至于采用什么樣的網(wǎng)絡(luò)融合手段,根據(jù)具體的場景進(jìn)行靈活運(yùn)用即可,如下圖是我們?nèi)诤锨昂蟮淖咏Y(jié)構(gòu)圖對比:

圖片

3.3.5 引擎優(yōu)化

  1. 多模型:由于外賣廣告中用戶請求規(guī)模不確定,廣告時(shí)多時(shí)少,為此加載多個(gè)模型,每個(gè)模型對應(yīng)不同輸入的Batch,將輸入規(guī)模分桶歸類劃分,并將其padding到多個(gè)固定Batch,同時(shí)對應(yīng)到相應(yīng)的模型進(jìn)行inference。
  2. Multi-contexts和Multi-streams:對每一個(gè)Batch的模型,使用多context和多stream,不僅可以避免模型等待同一context的開銷,而且可以充分利用多stream的并發(fā)性,實(shí)現(xiàn)stream間的overlap,同時(shí)為了更好的解決資源競爭的問題,引入CAS。如下圖所示,單stream變成多stream:

圖片

  1. Dynamic Shape:為了應(yīng)對輸入Batch不定場景下,不必要的數(shù)據(jù)padding,同時(shí)減少模型數(shù)量降低顯存等資源的浪費(fèi),引入Dynamic Shape,模型根據(jù)實(shí)際輸入數(shù)據(jù)進(jìn)行inference,減少數(shù)據(jù)padding和不必要的計(jì)算資源浪費(fèi),最終達(dá)到性能優(yōu)化和吞吐提升的目的。
  2. CUDA Graph:現(xiàn)代GPU每個(gè)operation(kernel運(yùn)行等)所花費(fèi)的時(shí)間至少是微秒級別,而且,將每個(gè)operation提交給GPU也會(huì)產(chǎn)生一些開銷(微秒級別)。實(shí)際inference時(shí),經(jīng)常需要執(zhí)行大量的kernel operation,這些operation每一個(gè)都單獨(dú)提交到GPU并獨(dú)立計(jì)算,如果可以把所有提交啟動(dòng)的開銷匯總到一起,應(yīng)該會(huì)帶來性能的整體提升。CUDA Graph可以完成這樣的功能,它將整個(gè)計(jì)算流程定義為一個(gè)圖而不是單個(gè)操作的列表,然后通過提供一種由單個(gè)CPU操作來啟動(dòng)圖上的多個(gè)GPU操作的方法減少kernel提交啟動(dòng)的開銷。CUDA Graph核心思想是減少kernel launch的次數(shù),通過在推理前后capture graph,根據(jù)推理的需要進(jìn)行update graph,后續(xù)推理時(shí)不再需要一次一次的kernel launch,只需要graph launch,最終達(dá)到減少kernel launch次數(shù)的目的。如下圖所示,一次inference執(zhí)行4次kernel相關(guān)操作,通過使用CUDA Graph可以清晰看到優(yōu)化效果。

圖片

  1. 多級PS:為了進(jìn)一步挖掘GPU加速引擎性能,對Embedding數(shù)據(jù)的查詢操作可通過多級PS的方式進(jìn)行:GPU顯存Cache->CPU內(nèi)存Cache->本地SSD/分布式KV。其中,熱點(diǎn)數(shù)據(jù)可緩存在GPU顯存中,并通過數(shù)據(jù)熱點(diǎn)的遷移、晉升和淘汰等機(jī)制對緩存數(shù)據(jù)進(jìn)行動(dòng)態(tài)更新,充分挖掘GPU的并行算力和訪存能力進(jìn)行高效查詢。經(jīng)離線測試,GPU Cache查詢性能相比CPU Cache提升10倍+;對于GPU Cache未命中數(shù)據(jù),可通過訪問CPU Cache進(jìn)行查詢,兩級Cache可滿足90%+的數(shù)據(jù)訪問;對于長尾請求,則需要通過訪問分布式KV進(jìn)行數(shù)據(jù)獲取。具體結(jié)構(gòu)如下:

圖片

3.3.6 Pipeline

模型從離線訓(xùn)練到最終在線加載,整個(gè)流程繁瑣易出錯(cuò),而且模型在不同GPU卡、不同TensorRT和CUDA版本上無法通用,這給模型轉(zhuǎn)換帶來了更多出錯(cuò)的可能性。因此,為了提升模型迭代的整體效率,我們在Pipeline方面進(jìn)行了相關(guān)能力建設(shè),如下圖所示:

圖片

Pipeline建設(shè)包括兩部分:離線側(cè)模型拆分轉(zhuǎn)換流程,以及在線側(cè)模型部署流程:

  1. 離線側(cè):只需提供模型拆分節(jié)點(diǎn),平臺(tái)會(huì)自動(dòng)將原始TF模型拆分成Embedding子模型和計(jì)算圖子模型,其中Embedding子模型通過分布式轉(zhuǎn)換器進(jìn)行分布式算子替換和Embedding導(dǎo)入工作;計(jì)算圖子模型則根據(jù)選擇的硬件環(huán)境(GPU型號、TensorRT版本、CUDA版本)進(jìn)行TensorRT模型的轉(zhuǎn)換和編譯優(yōu)化工作,最終將兩個(gè)子模型的轉(zhuǎn)換結(jié)果存儲(chǔ)到S3中,用于后續(xù)的模型部署上線。整個(gè)流程都是平臺(tái)自動(dòng)完成,無需使用方感知執(zhí)行細(xì)節(jié)。
  2. 在線測:只需選擇模型部署硬件環(huán)境(與模型轉(zhuǎn)換的環(huán)境保持一致),平臺(tái)會(huì)根據(jù)環(huán)境配置,進(jìn)行模型的自適應(yīng)推送加載,一鍵完成模型的部署上線。

Pipeline通過配置化、一鍵化能力的建設(shè),極大提升了模型迭代效率,幫助算法和工程同學(xué)能夠更加專注的做好本職工作。下圖是在GPU實(shí)踐中相比純CPU推理取得的整體收益:

圖片

4 特征服務(wù)CodeGen優(yōu)化

特征抽取是模型計(jì)算的前置階段,無論是傳統(tǒng)的LR模型還是日趨流行的深度學(xué)習(xí)模型,都需要通過特征抽取來得到輸入。在之前的博客??美團(tuán)外賣特征平臺(tái)的建設(shè)與實(shí)踐??中,描述了我們基于模型特征自描述MFDL,將特征計(jì)算流程配置化,盡量保證了在線預(yù)估和離線訓(xùn)練時(shí)樣本的一致性。隨著業(yè)務(wù)快速迭代,模型特征數(shù)量不斷增加,特別是大模型引入了大量的離散特征,導(dǎo)致計(jì)算量有了成倍的增長。為此,我們對特征抽取層做了一些優(yōu)化,在吞吐和耗時(shí)上都取得了顯著的收益。

4.1 全流程CodeGen優(yōu)化

DSL是對特征處理邏輯的描述。在早期的特征計(jì)算實(shí)現(xiàn)中,每個(gè)模型配置的DSL都會(huì)被解釋執(zhí)行。解釋執(zhí)行的優(yōu)點(diǎn)是實(shí)現(xiàn)簡單,通過良好的設(shè)計(jì)便能獲得較好的實(shí)現(xiàn),比如常用的迭代器模式;缺點(diǎn)是執(zhí)行性能較低,在實(shí)現(xiàn)層面為了通用性避免不了添加很多的分支跳轉(zhuǎn)和類型轉(zhuǎn)換等。實(shí)際上,對于一個(gè)固定版本的模型配置來說,它所有的模型特征轉(zhuǎn)換規(guī)則都是固定的,不會(huì)隨請求而變化。極端情況下,基于這些已知的信息,可以對每個(gè)模型特征各自進(jìn)行Hard Code,從而達(dá)到最極致的性能。顯然,模型特征配置千變?nèi)f化,不可能針對每個(gè)模型去人工編碼。于是便有了CodeGen的想法,在編譯期為每一個(gè)配置自動(dòng)生成一套專有的代碼。CodeGen并不是一項(xiàng)具體的技術(shù)或框架,而是一種思想,完成從抽象描述語言到具體執(zhí)行語言的轉(zhuǎn)換過程。其實(shí)在業(yè)界,計(jì)算密集型場景下使用CodeGen來加速計(jì)算已是常用做法。如Apache Spark通過CodeGen來優(yōu)化SparkSql執(zhí)行性能,從1.x的ExpressionCodeGen加速表達(dá)式運(yùn)算到2.x引入的WholeStageCodeGen進(jìn)行全階段的加速,都取得了非常明顯的性能收益。在機(jī)器學(xué)習(xí)領(lǐng)域,一些TF模型加速框架,如TensorFlow XLA和TVM,也是基于CodeGen思想,將Tensor節(jié)點(diǎn)編譯成統(tǒng)一的中間層IR,基于IR結(jié)合本地環(huán)境進(jìn)行調(diào)度優(yōu)化,從而達(dá)到運(yùn)行時(shí)模型計(jì)算加速的目的。

圖片

借鑒了Spark的WholeStageCodeGen,我們的目標(biāo)是將整個(gè)特征計(jì)算DSL編譯形成一個(gè)可執(zhí)行方法,從而減少代碼運(yùn)行時(shí)的性能損耗。整個(gè)編譯過程可以分為:前端(FrontEnd),優(yōu)化器(Optimizer)和后端(BackEnd)。前端主要負(fù)責(zé)解析目標(biāo)DSL,將源碼轉(zhuǎn)化為AST或IR;優(yōu)化器則是在前端的基礎(chǔ)上,對得到的中間代碼進(jìn)行優(yōu)化,使代碼更加高效;后端則是將已經(jīng)優(yōu)化的中間代碼轉(zhuǎn)化為針對各自平臺(tái)的本地代碼。具體實(shí)現(xiàn)如下:

  1. 前端:每個(gè)模型對應(yīng)一張節(jié)點(diǎn)DAG圖,逐個(gè)解析每個(gè)特征計(jì)算DSL,生成AST,并將AST節(jié)點(diǎn)添加到圖中。
  2. 優(yōu)化器:針對DAG節(jié)點(diǎn)進(jìn)行優(yōu)化,比如公共算子提取、常量折疊等。
  3. 后端:將經(jīng)過優(yōu)化后的圖編譯成字節(jié)碼。

圖片

經(jīng)過優(yōu)化之后,對節(jié)點(diǎn)DAG圖的翻譯,即后端代碼實(shí)現(xiàn),決定了最終的性能。這其中的一個(gè)難點(diǎn),同時(shí)也是不能直接使用已有開源表達(dá)式引擎的原因:特征計(jì)算DSL并非是一個(gè)純計(jì)算型表達(dá)式。它可以通過讀取算子和轉(zhuǎn)換算子的組合來描述特征的獲取和處理過程:

  1. 讀取算子:從存儲(chǔ)系統(tǒng)獲取特征的過程,是個(gè)IO型任務(wù)。比如查詢遠(yuǎn)程KV系統(tǒng)。
  2. 轉(zhuǎn)換算子:特征獲取到本地之后對特征進(jìn)行轉(zhuǎn)換,是個(gè)計(jì)算密集型任務(wù)。比如對特征值做Hash。

所以在實(shí)際實(shí)現(xiàn)中,需要考慮不同類型任務(wù)的調(diào)度,盡可能提高機(jī)器資源利用率,優(yōu)化流程整體耗時(shí)。結(jié)合對業(yè)界的調(diào)研以及自身實(shí)踐,進(jìn)行了以下三種實(shí)現(xiàn):

圖片

  1. 基于任務(wù)類型劃分Stage:將整個(gè)流程劃分成獲取和計(jì)算兩種Stage,Stage內(nèi)部分片并行處理,上一個(gè)Stage完成后再執(zhí)行下一個(gè)Stage。這是我們早期使用的方案,實(shí)現(xiàn)簡單,可以基于不同的任務(wù)類型選擇不同的分片大小,比如IO型任務(wù)可以使用更大的分片。但缺點(diǎn)也很明顯,會(huì)造成不同Stage的長尾疊加,每個(gè)Stage的長尾都會(huì)影響整個(gè)流程的耗時(shí)。
  2. 基于流水線劃分Stage:為了減少不同Stage的長尾疊加,可以先將數(shù)據(jù)分片,為每個(gè)特征讀取分片添加回調(diào),在IO任務(wù)完成后回調(diào)計(jì)算任務(wù),使整個(gè)流程像流水線一樣平滑。分片調(diào)度可以讓上一個(gè)Stage就緒更早的分片提前進(jìn)入下一個(gè)Stage,減少等待時(shí)間,從而減少整體請求耗時(shí)長尾。但缺點(diǎn)就是統(tǒng)一的分片大小不能充分提高每個(gè)Stage的利用率,較小的分片會(huì)給IO型任務(wù)帶來更多的網(wǎng)絡(luò)消耗,較大的分片會(huì)加劇計(jì)算型任務(wù)的耗時(shí)。
  3. 基于SEDA(Staged Event-Driven Architecture)方式:階段式事件驅(qū)動(dòng)方式使用隊(duì)列來隔離獲取Stage和計(jì)算Stage,每個(gè)Stage分配有獨(dú)立的線程池和批處理處理隊(duì)列,每次消費(fèi)N(batching factor)個(gè)元素。這樣既能夠?qū)崿F(xiàn)每個(gè)Stage單獨(dú)選擇分片大小,同時(shí)事件驅(qū)動(dòng)模型也可以讓流程保持平滑。這是我們目前正在探索的方式。

CodeGen方案也并非完美,動(dòng)態(tài)生成的代碼降低了代碼可讀性,增加了調(diào)試成本,但以CodeGen作為適配層,也為更深入的優(yōu)化打開了空間?;贑odeGen和異步非阻塞的實(shí)現(xiàn),在線上取到了不錯(cuò)的收益,一方面減少了特征計(jì)算的耗時(shí),另一方面也明顯的降低了CPU負(fù)載,提高了系統(tǒng)吞吐。未來我們會(huì)繼續(xù)發(fā)揮CodeGen的優(yōu)勢,在后端編譯過程中進(jìn)行針對性的優(yōu)化,如探索結(jié)合硬件指令(如SIMD)或異構(gòu)計(jì)算(如GPU)來做更深層次的優(yōu)化。

4.2 傳輸優(yōu)化

在線預(yù)估服務(wù)整體上是雙層架構(gòu),特征抽取層負(fù)責(zé)模型路由和特征計(jì)算,模型計(jì)算層負(fù)責(zé)模型計(jì)算。原有的系統(tǒng)流程是將特征計(jì)算后的結(jié)果拼接成M(預(yù)測的Batch Size) × N(樣本寬度)的矩陣,再經(jīng)過序列化傳輸?shù)接?jì)算層。之所以這么做,一方面出于歷史原因,早期很多非DNN的簡單模型的輸入格式是個(gè)矩陣,經(jīng)過路由層拼接后,計(jì)算層可以直接使用,無需轉(zhuǎn)換;另一方面,數(shù)組格式比較緊湊,可以節(jié)省網(wǎng)絡(luò)傳輸耗時(shí)。圖片然而隨著模型迭代發(fā)展,DNN模型逐漸成為主流,基于矩陣傳輸?shù)谋锥艘卜浅C黠@:

  1. 擴(kuò)展性差:數(shù)據(jù)格式統(tǒng)一,不兼容非數(shù)值類型的特征值。
  2. 傳輸性能損耗:基于矩陣格式,需要對特征做對齊,比如Query/User維度需要被拷貝對齊到每個(gè)Item上,增大了請求計(jì)算層的網(wǎng)絡(luò)傳輸數(shù)據(jù)量。

為了解決以上問題,優(yōu)化后的流程在傳輸層之上加入一層轉(zhuǎn)換層,用來根據(jù)MDFL的配置將計(jì)算的模型特征轉(zhuǎn)換成需要的格式,比如Tensor、矩陣或離線使用的CSV格式等。圖片實(shí)際線上大多數(shù)模型都是TF模型,為了進(jìn)一步節(jié)省傳輸消耗,平臺(tái)設(shè)計(jì)了Tensor Sequence格式來存儲(chǔ)每個(gè)Tensor矩陣:其中,r_flag用來標(biāo)記是否是item類特征,length表示item特征的長度,值為M(Item個(gè)數(shù))×NF(特征長度),data用來存儲(chǔ)實(shí)際的特征值,對于Item特征將M個(gè)特征值扁平化存儲(chǔ),對于請求類特征則直接填充。基于緊湊型Tensor Sequence格式使數(shù)據(jù)結(jié)構(gòu)更加緊湊,減少網(wǎng)絡(luò)傳輸數(shù)據(jù)量。優(yōu)化后的傳輸格式在線上也取得不錯(cuò)的效果,路由層調(diào)用計(jì)算層的請求大小下降了50%+,網(wǎng)絡(luò)傳輸耗時(shí)明顯下降。

4.3 高維ID特征編碼

離散特征和序列特征可以統(tǒng)一為Sparse特征,特征處理階段會(huì)把原始特征經(jīng)過Hash處理,變?yōu)镮D類特征。在面對千億級別維度的特征,基于字符串拼接再Hash的過程,在表達(dá)空間和性能上,都無法滿足要求?;趯I(yè)界的調(diào)研,我們設(shè)計(jì)和應(yīng)用了基于Slot編碼的方式特征編碼格式:

圖片

其中,feature_hash為原始特征值經(jīng)過Hash后的值。整型特征可以直接填充,非整型特征或交叉特征先經(jīng)過Hash后再填充,超過44位則截?cái)唷;赟lot編碼方案上線后,不僅提升了在線特征計(jì)算的性能,同時(shí)也為模型效果的帶來了明顯提升。

5 樣本構(gòu)建

5.1 流式樣本

業(yè)界為了解決線上線下一致性的問題,一般都會(huì)在線dump實(shí)時(shí)打分使用的特征數(shù)據(jù),稱為特征快照;而不是通過簡單離線Label拼接,特征回填的方式來構(gòu)建樣本,因?yàn)檫@種方式會(huì)帶來較大的數(shù)據(jù)不一致。架構(gòu)原始的方式如下圖所示:

圖片

這種方案隨著特征規(guī)模越來越大、迭代場景越來越復(fù)雜,突出的問題就是在線特征抽取服務(wù)壓力大,其次是整個(gè)數(shù)據(jù)流收集成本太高。此樣本收集方案存在以下問題:

  1. 就緒時(shí)間長:在現(xiàn)有資源限制下,跑那么大數(shù)據(jù)幾乎要在T+2才能將樣本數(shù)據(jù)就緒,影響算法模型迭代。
  2. 資源耗費(fèi)大:現(xiàn)有樣本收集方式是將所有請求計(jì)算特征后與曝光、點(diǎn)擊進(jìn)行拼接,由于對未曝光Item進(jìn)行了特征計(jì)算、數(shù)據(jù)落表,導(dǎo)致存儲(chǔ)的數(shù)據(jù)量較大,耗費(fèi)大量資源。

5.1.1 常見的方案

為了解決上面的問題,業(yè)界常見有兩個(gè)方案:①Flink實(shí)時(shí)流處理;②KV緩存二次處理。具體流程如下圖所示:

圖片


  1. 流式拼接方案:借助流式處理框架(Flink、Storm等)低延遲的流處理能力,直接讀取曝光/點(diǎn)擊實(shí)時(shí)流,與特征快照流數(shù)據(jù)在內(nèi)存中進(jìn)行關(guān)聯(lián)(Join)處理;先生成流式訓(xùn)練樣本,再轉(zhuǎn)存為模型離線訓(xùn)練樣本。其中流式樣本和離線樣本分別存儲(chǔ)在不同的存儲(chǔ)引擎中,支持不同類型的模型訓(xùn)練方式。此方案的問題:在數(shù)據(jù)流動(dòng)環(huán)節(jié)的數(shù)據(jù)量依然很大,占用較多的消息流資源(比如Kafka);Flink資源消耗過大,如果每秒百G的數(shù)據(jù)量,做窗口Join則需要30分鐘×60×100G的內(nèi)存資源。
  2. KV緩存方案:把特征抽取的所有特征快照寫入KV存儲(chǔ)(如Redis)緩存N分鐘,業(yè)務(wù)系統(tǒng)通過消息機(jī)制,把候選隊(duì)列中的Item傳入到實(shí)時(shí)計(jì)算系統(tǒng)(Flink或者消費(fèi)應(yīng)用),此時(shí)的Item的量會(huì)比之前請求的Item量少很多,這樣再將這些Item特征從特征快照緩存中取出,數(shù)據(jù)通過消息流輸出,支持流式訓(xùn)練。這種方法借助了外存,不管隨著特征還是流量增加,F(xiàn)link資源可控,而且運(yùn)行更加穩(wěn)定。但突出的問題還是需要較大的內(nèi)存來緩存大批量數(shù)據(jù)。

5.1.2 改進(jìn)優(yōu)化

從減少無效計(jì)算的角度出發(fā),請求的數(shù)據(jù)并不會(huì)都曝光。而策略對曝光后的數(shù)據(jù)有更強(qiáng)的需求,因此將天級處理前置到流處理,可以極大提升數(shù)據(jù)就緒時(shí)間。其次,從數(shù)據(jù)內(nèi)容出發(fā),特征包含請求級變更的數(shù)據(jù)與天級變更的數(shù)據(jù),鏈路靈活分離兩者處理,可以極大提升資源的利用,下圖是具體的方案:

圖片

1. 數(shù)據(jù)拆分:解決數(shù)據(jù)傳輸量大問題(特征快照流大問題),預(yù)測的Label與實(shí)時(shí)數(shù)據(jù)一一Match,離線數(shù)據(jù)可以通過回流的時(shí)候二次訪問,這樣可以極大降低鏈路數(shù)據(jù)流的大小。

  • 樣本流中只有上下文+實(shí)時(shí)特征,增加讀取數(shù)據(jù)流穩(wěn)定性,同時(shí)由于只需要存儲(chǔ)實(shí)時(shí)特征,Kafka硬盤存儲(chǔ)下降10+倍。

2. 延時(shí)消費(fèi)Join方式:解決占用內(nèi)存大問題。

  • 曝光流作為主流,寫入到HBase中,同時(shí)為了后續(xù)能讓其他流在HBase中Join上曝光,將RowKey寫入Redis;后續(xù)流通過RowKey寫入HBase,曝光與點(diǎn)擊、特征的拼接借助外存完成,保證數(shù)據(jù)量增大后系統(tǒng)能穩(wěn)定運(yùn)行。
  • 樣本流延時(shí)消費(fèi),后臺(tái)服務(wù)的樣本流往往會(huì)比曝光流先到,為了能Join上99%+的曝光數(shù)據(jù),樣本流等待窗口統(tǒng)計(jì)至少要N分鐘以上;實(shí)現(xiàn)方式是將窗口期的數(shù)據(jù)全部壓在Kafka的磁盤上,利用磁盤的順序讀性能,省略掉了窗口期內(nèi)需要緩存數(shù)據(jù)量的大量內(nèi)存。

3. 特征補(bǔ)錄拼樣本:通過Label的Join,此處補(bǔ)錄的特征請求量不到在線的20%;樣本延遲讀取,與曝光做拼接后過濾出有曝光模型服務(wù)請求(Context+實(shí)時(shí)特征),再補(bǔ)錄全部離線特征,拼成完整樣本數(shù)據(jù),寫入HBase。

5.2 結(jié)構(gòu)化存儲(chǔ)

隨著業(yè)務(wù)迭代,特征快照中的特征數(shù)量越來越大,使得整體特征快照在單業(yè)務(wù)場景下達(dá)到幾十TB級別/天;從存儲(chǔ)上看,多天單業(yè)務(wù)的特征快照就已經(jīng)PB級別,快到達(dá)廣告算法存儲(chǔ)閾值,存儲(chǔ)壓力大;從計(jì)算角度上看,使用原有的計(jì)算流程,由于計(jì)算引擎(Spark)的資源限制(使用到了shuffle,shuffle write階段數(shù)據(jù)會(huì)落盤,如果分配內(nèi)存不足,會(huì)出現(xiàn)多次落盤和外排序),需要與自身數(shù)據(jù)等大小的內(nèi)存和較多的計(jì)算CU才能有效的完成計(jì)算,占用內(nèi)存高。樣本構(gòu)建流程核心流程如下圖所示:

圖片

在補(bǔ)錄特征時(shí),存在以下問題:

  1. 數(shù)據(jù)冗余:補(bǔ)錄特征的離線表一般為全量數(shù)據(jù),條數(shù)在億級別,樣本構(gòu)建用到的條數(shù)約為當(dāng)日DAU的數(shù)量即千萬級別,因此補(bǔ)錄的特征表數(shù)據(jù)在參與計(jì)算時(shí)存在冗余數(shù)據(jù)。
  2. Join順序:補(bǔ)錄特征的計(jì)算過程即維度特征補(bǔ)全,存在多次Join計(jì)算,因此Join計(jì)算的性能和Join的表的順序有很大關(guān)系,如上圖所示,如果左表為幾十TB級別的大表,那么之后的shuffle計(jì)算過程都會(huì)產(chǎn)生大量的網(wǎng)絡(luò)IO、磁盤IO。

為了解決樣本構(gòu)建效率慢的問題,短期先從數(shù)據(jù)結(jié)構(gòu)化治理,詳細(xì)過程如下圖所示:

圖片

  1. 結(jié)構(gòu)化拆分。數(shù)據(jù)拆分成Context數(shù)據(jù)和結(jié)構(gòu)化存儲(chǔ)的維度數(shù)據(jù)代替混合存儲(chǔ)。解決Label樣本拼接新特征過程中攜帶大量冗余數(shù)據(jù)問題;并且做結(jié)構(gòu)化存儲(chǔ)后,針對離線特征,得到了很大的存儲(chǔ)壓縮。
  2. 高效過濾前置。數(shù)據(jù)過濾提前到Join前,減少參與特征計(jì)算的數(shù)據(jù)量,可以有效降低網(wǎng)絡(luò)IO。在拼接過程中,補(bǔ)錄特征的Hive表一般來說是全量表,數(shù)據(jù)條數(shù)一般為月活量,而實(shí)際拼接過程中使用的數(shù)據(jù)條數(shù)約為日活量,因此存在較大的數(shù)據(jù)冗余,無效的數(shù)據(jù)會(huì)帶來額外的IO和計(jì)算。優(yōu)化方式為預(yù)計(jì)算使用的維度Key,并生成相應(yīng)的布隆過濾器,在數(shù)據(jù)讀取的時(shí)候使用布隆過濾器進(jìn)行過濾,可以極大降低補(bǔ)錄過程中冗余數(shù)據(jù)傳輸和冗余計(jì)算。
  3. 高性能Join。使用高效的策略去編排Join順序,提升特征補(bǔ)錄環(huán)節(jié)的效率和資源占用。在特征拼接過程中,會(huì)存在多張表的Join操作,Join的先后順序也會(huì)極大影響拼接性能。如上圖所示,如果拼接的左表數(shù)據(jù)量較大時(shí),那么整體性能就會(huì)差??梢允褂霉蚵惴ǖ乃枷?,把每個(gè)表看作一個(gè)節(jié)點(diǎn),對應(yīng)的數(shù)據(jù)量量看成是他的權(quán)重,表之間的Join計(jì)算量可以簡單類比兩個(gè)節(jié)點(diǎn)的權(quán)重相加。因此,可以將此問題抽象成構(gòu)造哈夫曼樹,哈夫曼樹的構(gòu)造過程即為最優(yōu)的Join順序。

數(shù)據(jù)離線存儲(chǔ)資源節(jié)省達(dá)80%+,樣本構(gòu)建效率提升200%+,當(dāng)前整個(gè)樣本數(shù)據(jù)也正在進(jìn)行基于數(shù)據(jù)湖的實(shí)踐,進(jìn)一步提升數(shù)據(jù)效率。

6 數(shù)據(jù)準(zhǔn)備

平臺(tái)積累了大量的特征、樣本和模型等有價(jià)值的內(nèi)容,希望通過對這些數(shù)據(jù)資產(chǎn)進(jìn)行復(fù)用,幫助策略人員更好的進(jìn)行業(yè)務(wù)迭代,取得更好的業(yè)務(wù)收益。特征優(yōu)化占了算法人員提升模型效果的所有方法中40%的時(shí)間,但傳統(tǒng)的特征挖掘的工作方式存在著花費(fèi)時(shí)間長、挖掘效率低、特征重復(fù)挖掘等問題,所以平臺(tái)希望在特征維度賦能業(yè)務(wù)。如果有自動(dòng)化的實(shí)驗(yàn)流程去驗(yàn)證任意特征的效果,并將最終效果指標(biāo)推薦給用戶,無疑會(huì)幫助策略同學(xué)節(jié)省大量的時(shí)間。當(dāng)整個(gè)鏈路建設(shè)完成,后續(xù)只需要輸入不同的特征候選集,即可輸出相應(yīng)效果指標(biāo)。為此平臺(tái)建設(shè)了特征、樣本的“加”、“減”、“乘”、“除”智能機(jī)制。

6.1 做“加法”

特征推薦基于模型測試的方法,將特征復(fù)用到其他業(yè)務(wù)線現(xiàn)有模型,構(gòu)造出新的樣本和模型;對比新模型和Base模型的離線效果,獲取新特征的收益,自動(dòng)推送給相關(guān)的業(yè)務(wù)負(fù)責(zé)人。具體特征推薦流程如下圖所示:

圖片

  1. 特征感知:通過上線墻或業(yè)務(wù)間存量方式觸發(fā)特征推薦,這些特征已經(jīng)過一定驗(yàn)證,可以保證特征推薦的成功率。
  2. 樣本生產(chǎn):樣本生產(chǎn)時(shí)通過配置文件抽取特征,流程自動(dòng)將新增特征加到配置文件中,然后進(jìn)行新樣本數(shù)據(jù)的生產(chǎn)。獲取到新特征后,解析這些特征依賴的原始特征、維度、和UDF算子等,將新特征配置和依賴的原始數(shù)據(jù)融合到基線模型的原有配置文件中,構(gòu)造出新的特征配置文件。自動(dòng)進(jìn)行新樣本構(gòu)建,樣本構(gòu)建時(shí)通過特征名稱在特征倉庫中抽取相關(guān)特征,并調(diào)用配置好的UDF進(jìn)行特征計(jì)算,樣本構(gòu)建的時(shí)間段可配置。
  3. 模型訓(xùn)練:自動(dòng)對模型結(jié)構(gòu)和樣本格式配置進(jìn)行改造,然后進(jìn)行模型訓(xùn)練,使用TensorFlow作為模型訓(xùn)練框架,使用tfrecord格式作為樣本輸入,將新特征按照數(shù)值類和ID類分別放到A和B兩個(gè)組中,ID類特征進(jìn)行查表操作,然后統(tǒng)一追加到現(xiàn)有特征后面,不需要修改模型結(jié)構(gòu)便可接收新的樣本進(jìn)行模型訓(xùn)練。
  4. 自動(dòng)配置新模型訓(xùn)練參數(shù):包括訓(xùn)練日期、樣本路徑、模型超參等,劃分出訓(xùn)練集和測試集,自動(dòng)進(jìn)行新模型的訓(xùn)練。
  5. 模型評測:調(diào)用評估接口得到離線指標(biāo),對比新老模型評測結(jié)果,并預(yù)留單特征評估結(jié)果,打散某些特征后,給出單特征貢獻(xiàn)度。將評估結(jié)果統(tǒng)一發(fā)送給用戶。

圖片

6.2 做“減法”

特征推薦在廣告內(nèi)部落地并取得了一定收益后,我們在特征賦能層面做一些新的探索。隨著模型的不斷優(yōu)化,特征膨脹的速度非???,模型服務(wù)消耗資源急劇上升,剔除冗余特征,為模型“瘦身”勢在必行。因此,平臺(tái)建設(shè)了一套端到端的特征篩選工具。

圖片

  1. 特征打分:通過WOE(Weight Of Evidence, 證據(jù)權(quán)重)等多種評估算法給出模型的所有特征評分,打分較高特征的質(zhì)量較高,評估準(zhǔn)確率高。
  2. 效果驗(yàn)證:訓(xùn)練好模型后,按打分排序,分批次對特征進(jìn)行剔除。具體通過采用特征打散的方法,對比原模型和打散后模型評估結(jié)果,相差較大低于閾值后結(jié)束評估, 給出可以剔除的特征。
  3. 端到端方案:用戶配置好實(shí)驗(yàn)參數(shù)和指標(biāo)閾值后,無需人為干涉,即可給出可刪除的特征以及刪除特征后模型的離線評估結(jié)果。

最終,在內(nèi)部模型下線40%的特征后,業(yè)務(wù)指標(biāo)下降仍然控制在合理的閾值內(nèi)。

6.3 做“乘法”

為了得到更好的模型效果,廣告內(nèi)部已經(jīng)開始做一些新的探索,包括大模型、實(shí)時(shí)化、特征庫等。這些探索背后都有一個(gè)關(guān)鍵目標(biāo):需要更多、更好的數(shù)據(jù)讓模型更智能、更高效。從廣告現(xiàn)狀出發(fā),提出樣本庫(Data Bank)建設(shè),實(shí)現(xiàn)把外部更多種類、更大規(guī)模的數(shù)據(jù)拿進(jìn)來,應(yīng)用于現(xiàn)有業(yè)務(wù)。具體如下圖所示:

圖片

我們建立了一套通用的樣本共享平臺(tái),在這個(gè)平臺(tái)上,可以借用其他業(yè)務(wù)線來產(chǎn)生增量樣本。并且也搭建通用的Embedding共享架構(gòu),實(shí)現(xiàn)業(yè)務(wù)的以大帶小。下面以廣告業(yè)務(wù)線復(fù)用非廣告樣本為例,具體做法如下:

  1. 擴(kuò)樣本:基于Flink流式處理框架,建設(shè)了高擴(kuò)展樣本庫DataBank,業(yè)務(wù)A很方便復(fù)用業(yè)務(wù)B、業(yè)務(wù)C的曝光、點(diǎn)擊等Label數(shù)據(jù)去做實(shí)驗(yàn)。尤其是為小業(yè)務(wù)線,擴(kuò)充了大量的價(jià)值數(shù)據(jù),這種做法相比離線補(bǔ)錄Join,一致性會(huì)更強(qiáng),特征平臺(tái)提供了在線、離線一致性保障。
  2. 做共享:在樣本就緒后,一個(gè)很典型的應(yīng)用場景就是遷移學(xué)習(xí)。另外,也搭建Embedding共享的數(shù)據(jù)通路(不強(qiáng)依賴“擴(kuò)樣本”流程),所有業(yè)務(wù)線可以基于大的Embedding訓(xùn)練,每個(gè)業(yè)務(wù)方也可以update這個(gè)Embedding,在線通過建立Embedding版本機(jī)制,供多個(gè)業(yè)務(wù)線使用。

舉例來說,通過將非廣告樣本復(fù)用到廣告內(nèi)一個(gè)業(yè)務(wù),使樣本數(shù)量增加了幾倍,結(jié)合遷移學(xué)習(xí)算法,離線AUC提升千分之四,上線后CPM提升百分之一。此外,我們也在建設(shè)廣告樣本主題庫,將各業(yè)務(wù)生成的樣本數(shù)據(jù)進(jìn)行統(tǒng)一管理(統(tǒng)一元數(shù)據(jù)),面向用戶透出統(tǒng)一樣本主題分類,快速注冊、查找、復(fù)用,面向底層統(tǒng)一存儲(chǔ),節(jié)約存儲(chǔ)、計(jì)算資源,減少數(shù)據(jù)Join,提高時(shí)效性。

6.4 做“除法”

通過特征“減法”可以剔除一些無正向作用的特征,但通過觀察發(fā)現(xiàn)模型中還存在很多價(jià)值很小的特征。所以更進(jìn)一步我們可以通過價(jià)值、成本兩方面綜合考慮,在全鏈路基于成本的約束下價(jià)值最大,篩選出那些投入產(chǎn)出比較低特征,降低資源消耗。這個(gè)在成本約束下去求解的過程定義為做“除法”,整體流程如下圖所示。

圖片

在離線維度,我們建立了一套特征價(jià)值評估系統(tǒng),給出特征的成本和價(jià)值,在線推理時(shí)可以通過特征價(jià)值信息進(jìn)行流量降級、特征彈性計(jì)算等操作,做“除法”關(guān)鍵步驟如下:

  1. 問題抽象:如果我們能得到每個(gè)特征的價(jià)值得分,又可以拿到特征的成本(存儲(chǔ)、通信、計(jì)算加工),那么問題就轉(zhuǎn)換成了在已知模型結(jié)構(gòu)、固定資源成本下,如何讓特征的價(jià)值最大化。
  2. 成本約束下的價(jià)值評估:基于模型的特征集,平臺(tái)首先進(jìn)行成本和價(jià)值的統(tǒng)計(jì)匯總;成本包括了離線成本和在線成本,基于訓(xùn)練好的評判模型,得出特征的綜合排序。
  3. 分場景建模:可以根據(jù)不同的資源情況,選擇不同的特征集,進(jìn)行建模。在有限的資源下,選擇價(jià)值最大的模型在線Work。另外,可以針對比較大的特征集建模,在流量低峰啟用,提升資源利用率的同時(shí)給業(yè)務(wù)帶來更大收益。還有一種應(yīng)用場景是流量降級,推理服務(wù)監(jiān)控在線資源的消耗,一旦資源計(jì)算達(dá)到瓶頸,切換到降級模型。

7 總結(jié)與展望

以上是我們在大規(guī)模深度學(xué)習(xí)工程上的反“增”實(shí)踐,去助力業(yè)務(wù)降本提效。未來我們還會(huì)持續(xù)在以下方面進(jìn)行探索、實(shí)踐:

  1. 全鏈路GPU化:在推理層面,通過GPU的切換,支撐更復(fù)雜業(yè)務(wù)迭代的同時(shí),整體成本也極大的降低,后面會(huì)在樣本構(gòu)建、特征服務(wù)上進(jìn)行GPU化改造,并協(xié)同推進(jìn)離線訓(xùn)練層面的升級。
  2. 樣本數(shù)據(jù)湖:通過數(shù)據(jù)湖的Schema Evolution、Patch Update等特性構(gòu)建更大規(guī)模的樣本倉庫,對業(yè)務(wù)方進(jìn)行低成本、高價(jià)值的數(shù)據(jù)透出。
  3. Pipeline:算法全生命周期迭代過程中,很多環(huán)節(jié)的調(diào)試,鏈路信息都不夠“串聯(lián)”,以及離線、在線、效果指標(biāo)的視角都比較割裂,基于全鏈路的標(biāo)準(zhǔn)化、可觀測大勢所趨,并且這是后續(xù)鏈路智能化彈性調(diào)配的基礎(chǔ)。現(xiàn)在業(yè)界比較火的MLOps、云原生都有較多的借鑒思路。
  4. 數(shù)據(jù)、模型智能匹配:上文提到在模型結(jié)構(gòu)固定前提下,自動(dòng)為模型加、減特征,同理在模型層面,固定一定特征輸入前提下,去自動(dòng)嵌入一些新的模型結(jié)構(gòu)。以及在未來,我們也將基于業(yè)務(wù)領(lǐng)域,通過平臺(tái)的特征、模型體系,自動(dòng)化地完成數(shù)據(jù)、模型的匹配。

8 本文作者

亞劼、英亮、陳龍、成杰、登峰、東奎、仝曄、思敏、樂彬等,均來自美團(tuán)外賣技術(shù)團(tuán)隊(duì)。

責(zé)任編輯:張燕妮 來源: 美團(tuán)技術(shù)團(tuán)隊(duì)
相關(guān)推薦

2023-05-26 08:39:44

深度學(xué)習(xí)Alluxio

2023-06-28 08:23:41

搜索語義模型

2017-03-07 13:14:04

深度學(xué)習(xí)

2021-04-22 13:38:21

前端開發(fā)技術(shù)

2017-04-13 09:18:02

深度學(xué)習(xí)文本分類

2023-04-06 16:29:18

模型AI

2012-07-09 16:43:59

2023-01-03 16:54:27

字節(jié)跳動(dòng)深度學(xué)習(xí)

2012-07-27 15:47:18

YouTube

2024-08-29 12:56:03

2022-04-29 09:10:00

算法人工智能技術(shù)

2013-03-22 14:44:52

大規(guī)模分布式系統(tǒng)飛天開放平臺(tái)

2016-01-12 14:59:40

分布式存儲(chǔ)分布式存儲(chǔ)架構(gòu)

2025-03-06 10:33:04

2022-03-15 18:33:34

URL重構(gòu)Dubbo3.0

2021-09-06 11:15:05

數(shù)據(jù)治理字節(jié)跳動(dòng)埋點(diǎn)

2023-04-26 00:59:49

嗶哩嗶哩工程優(yōu)化

2018-10-29 15:50:23

深度學(xué)習(xí)工程實(shí)踐技術(shù)

2020-06-10 10:00:53

Serverless數(shù)據(jù)處理函數(shù)

2016-04-15 00:43:13

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號