基于Spark的大規(guī)模推薦系統(tǒng)特征工程
分享嘉賓:陳迪豪?第四范式?架構(gòu)師
編輯整理:劉璐
出品平臺(tái):第四范式天樞、DataFunTalk
-
大規(guī)模推薦系統(tǒng)
-
Spark SQL應(yīng)用與FESQL
-
基于LLVM的Spark優(yōu)化
-
總結(jié)
1. 業(yè)界推薦系統(tǒng)的應(yīng)用
眾所周知,推薦系統(tǒng)在業(yè)界有著許多成功的應(yīng)用,據(jù)統(tǒng)計(jì),亞馬遜40%的銷售在推薦系統(tǒng)的作用下產(chǎn)生;Netflix 75%的用戶使用推薦系統(tǒng)尋找他們喜愛(ài)的視頻;30%的用戶進(jìn)行在線購(gòu)物前會(huì)使用關(guān)鍵詞搜索他們需要的商品。目前,幾乎所有的新聞、搜索、廣告、短視頻應(yīng)用都是基于推薦系統(tǒng)建立的。
2. 推薦系統(tǒng)的架構(gòu)
業(yè)界成熟的推薦系統(tǒng)架構(gòu)一般分為三層:離線層 ( offline layer ),近實(shí)時(shí)的流式層 ( stream layer ) 和在線層 ( online layer ) 三部分。
離線層:一般用于大規(guī)模的數(shù)據(jù)預(yù)處理、特征抽取與模型訓(xùn)練,通常用Hadoop HDFS進(jìn)行數(shù)據(jù)存儲(chǔ),使用Spark,MapReduce等分布式計(jì)算引擎進(jìn)行特征抽取與計(jì)算以及數(shù)據(jù)管理,再使用離線模型訓(xùn)練框架TensorFlow、Pytorch、MXNet等進(jìn)行離線的模型訓(xùn)練,模型結(jié)果可用于線上預(yù)測(cè)。
近實(shí)時(shí)的流式層:主要是為了提升推薦系統(tǒng)的時(shí)效性,對(duì)于一些時(shí)序特征,可以使用消息隊(duì)列收集近實(shí)時(shí)的數(shù)據(jù),結(jié)合流式計(jì)算服務(wù)如Flink對(duì)數(shù)據(jù)進(jìn)行補(bǔ)全,把結(jié)果存入NoSQL、MySQL等存儲(chǔ)服務(wù)中,存儲(chǔ)結(jié)果供線上服務(wù)使用。
在線層:用戶產(chǎn)生的數(shù)據(jù)可以通過(guò)Flink生成流式特征,也可以使用HDFS進(jìn)行數(shù)據(jù)歸檔。在線預(yù)估時(shí)從NoSQL或MySQL中提取流式特征,通過(guò)離線訓(xùn)練的模型即可進(jìn)行線上預(yù)估。
3. 大規(guī)模推薦系統(tǒng)的特征抽取
大規(guī)模推薦系統(tǒng)的數(shù)據(jù)處理通常分為兩類:
-
ETL ( Extract, Transform, Load ):進(jìn)行數(shù)據(jù)數(shù)據(jù)補(bǔ)全、格式轉(zhuǎn)換等;
-
特征抽?。簩?duì)原始數(shù)據(jù)特征進(jìn)行處理,得到模型易于學(xué)習(xí)的樣本特征,如離散化,embedding化等方法。
常用工具包括:
-
SQL/Python:針對(duì)一般規(guī)模的數(shù)據(jù),通??梢酝ㄟ^(guò)使用SQL/Python進(jìn)行處理;
-
Hadoop/Spark/Flink:針對(duì)大規(guī)模數(shù)據(jù),通常要借助Hadoop/Spark/Flink等計(jì)算框架。
1. Spark簡(jiǎn)介
Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎,依托強(qiáng)大的分布式計(jì)算能力,在Spark上可以開(kāi)發(fā)機(jī)器學(xué)習(xí)、流式學(xué)習(xí)等應(yīng)用。Spark提供了SparkSQL,使其能與SQL、Hive兼容,提供PySpark接口可以讓開(kāi)發(fā)者使用Python進(jìn)行分布式應(yīng)用開(kāi)發(fā),提供了MLlib包,可以用于機(jī)器學(xué)習(xí)應(yīng)用的開(kāi)發(fā)。同時(shí)Spark也提供諸如Catalyst/Tungsten等方式的優(yōu)化。
Spark的優(yōu)勢(shì)就在于:計(jì)算速度快,能夠處理PB級(jí)別的數(shù)據(jù),分布式計(jì)算和自動(dòng)容錯(cuò)機(jī)制,提供便于使用的SQL/Python/R API,同時(shí),Spark提供的機(jī)器學(xué)習(xí)庫(kù)也可以應(yīng)用于推薦系統(tǒng),所以在業(yè)界,幾乎所有公司都會(huì)使用Spark作為離線層數(shù)據(jù)處理框架。
2. 大規(guī)模推薦系統(tǒng)中的Spark應(yīng)用
以IBM的一個(gè)推薦系統(tǒng)開(kāi)源項(xiàng)目來(lái)說(shuō)明Spark在推薦系統(tǒng)中的應(yīng)用。首先是數(shù)據(jù)加載,使用read.csv即可加載本地或HDFS數(shù)據(jù)。使用select即可進(jìn)行特征列選擇。
然后是對(duì)數(shù)據(jù)進(jìn)行預(yù)處理以及簡(jiǎn)單的特征抽取,該項(xiàng)目中使用了Spark UDF對(duì)字符串進(jìn)行處理,抽取出其中的年份信息,將年份信息作為特征進(jìn)行使用。
得到全部特征預(yù)處理的結(jié)果后即可進(jìn)行模型訓(xùn)練,可以使用Spark內(nèi)置機(jī)器學(xué)習(xí)API進(jìn)行模型訓(xùn)練。訓(xùn)練完成后,模型即可上線進(jìn)行線上預(yù)估。
線上的預(yù)估服務(wù)需要提供實(shí)時(shí)計(jì)算的預(yù)估接口,但是在實(shí)踐中,Spark并不適合直接用于線上預(yù)估。原因有三:
-
Driver-exexutor結(jié)構(gòu)只適合進(jìn)行批量處理,不適合在線處理
-
Spark的批處理模式不適合提供長(zhǎng)時(shí)間運(yùn)行的在線服務(wù),也不能保證低延時(shí)的計(jì)算效率(Spark 3.0的Hydrogen可以部分支持)
-
RDD接口只適合迭代計(jì)算,不適合做實(shí)時(shí)計(jì)算
因此,業(yè)界的通常做法是使用Java、C++等后端語(yǔ)言實(shí)現(xiàn)在線的預(yù)估服務(wù),這就帶來(lái)了另一個(gè)線上特征抽取的一致性問(wèn)題,由于必須要保證線上線下特征的一致性,所以必須同時(shí)開(kāi)發(fā)線上使用的特征處理模塊,并人工保證計(jì)算結(jié)果沒(méi)有差異。
3. Spark的優(yōu)缺點(diǎn)
Spark支持大規(guī)模數(shù)據(jù)的批處理,提供標(biāo)準(zhǔn)的SQL接口的優(yōu)點(diǎn)使其成為離線層數(shù)據(jù)處理的不二之選,但是,Spark不支持線上服務(wù),不能保證線上線下特征一致性,同時(shí)在AI場(chǎng)景下的性能沒(méi)有經(jīng)過(guò)優(yōu)化,所以在AI場(chǎng)景下,Spark仍有許多不足。針對(duì)這些不足,第四范式開(kāi)發(fā)了FESQL執(zhí)行引擎。
4. FESQL線上線下一致性執(zhí)行引擎
FESQL——保證離線在線特征一致性的SQL執(zhí)行引擎。上圖表示傳統(tǒng)的上線過(guò)程,生成離線模型文件后,由應(yīng)用開(kāi)發(fā)者開(kāi)發(fā)線上預(yù)估服務(wù),將Spark、SQL中的特征處理邏輯翻譯成后端語(yǔ)言代碼,實(shí)現(xiàn)線上服務(wù),每新增一個(gè)特征,都要開(kāi)發(fā)對(duì)應(yīng)的特征抽取模塊,同時(shí)需要用戶和業(yè)務(wù)開(kāi)發(fā)者保證特征數(shù)據(jù)的一致性。下圖是使用FESQL的上線過(guò)程,由于線上線下使用統(tǒng)一的SQL服務(wù)進(jìn)行特征抽取,因而保證了特征在線上和線下的一致性。
圖中所示為FESQL基本框架,左邊離線部分和SparkSQL的用法基本一致,由數(shù)據(jù)科學(xué)家設(shè)計(jì)SQL語(yǔ)句,基于Spark進(jìn)行離線批處理。橙色框表示第四范式開(kāi)發(fā)的基于LLVM優(yōu)化的SQL引擎,性能大大優(yōu)于原生Spark,同時(shí)能夠更好的支持線上服務(wù),尤其對(duì)于SQL語(yǔ)句進(jìn)行了拓展,使之能夠更好的支持機(jī)器學(xué)習(xí)場(chǎng)景下的線上特征處理。其中FEDB是有第四范式開(kāi)發(fā)的全內(nèi)存數(shù)據(jù)庫(kù),相比于Spark讀取HDFS這種高延時(shí)的數(shù)據(jù)載入方式,F(xiàn)EDB可以提前載入模型預(yù)估所需數(shù)據(jù),效果接近開(kāi)發(fā)的線上特征抽取模塊,同時(shí)支持時(shí)序特征。線上線下的數(shù)據(jù)一致性由同一套的SQL執(zhí)行引擎保證。
5. 性能對(duì)比
與兼容SQL的全內(nèi)存數(shù)據(jù)庫(kù)memsql的方式進(jìn)行性能對(duì)比可以發(fā)現(xiàn),LLVM優(yōu)化后的SQL之心引擎在讀和寫(xiě)的性能上都要更高。
對(duì)于機(jī)器學(xué)習(xí)場(chǎng)景下的列聚合 ( 生成時(shí)序特征 ) 場(chǎng)景,LLVM優(yōu)化后的SQL引擎也比memsql快很多,耗時(shí)基本小于memsql的50%。
1. Spark Catalyst和Tungsten優(yōu)化
Spark2.0之后提供了Catalyst和Tungsten優(yōu)化。圖為Catalyst從SQL解析到生成物理計(jì)劃的流程圖,由SQL語(yǔ)句或DataFrame接口通過(guò)編譯器技術(shù) ( 語(yǔ)法解析等 ) 生成Unresolved Logical Plan,Catalyst通過(guò)解析Catalog對(duì)Unresolved Logical Plan處理得到Logical Plan,在經(jīng)過(guò)SQL常用優(yōu)化方案,得到Optimized Logical Plan,優(yōu)化之Catalyst后可以生成多個(gè)基于Spark運(yùn)行的Physical Plan,最終選擇其中最高效的進(jìn)行運(yùn)行。該方式適合于計(jì)算節(jié)點(diǎn)優(yōu)化,對(duì)于SQL的優(yōu)化也同樣效果顯著。
Tungsten是另外一種優(yōu)化方案。主要的優(yōu)化點(diǎn)在于:
-
內(nèi)存管理與堆外存儲(chǔ)避免了多余的內(nèi)存使用,同時(shí)減少了GC;
-
引入code generation技術(shù),通過(guò)JIT編譯運(yùn)行,Spark動(dòng)態(tài)生成Java字節(jié)碼來(lái)計(jì)算這些表達(dá)式,而不是為逐行解析執(zhí)行,減少了原始數(shù)據(jù)類型的裝箱操作,更重要的是避免了Overhead較大的虛函數(shù)調(diào)用。
以一個(gè)經(jīng)典實(shí)例來(lái)介紹Tungsten的原理。左側(cè)的SQL命令可以翻譯成在Spark上運(yùn)行的Logical Plan,由下往上分為4個(gè)計(jì)算節(jié)點(diǎn),傳統(tǒng)的SQL執(zhí)行引擎中,四個(gè)節(jié)點(diǎn)分別由四個(gè)迭代器實(shí)現(xiàn) ( 可以理解為四個(gè)循環(huán) ),循環(huán)沒(méi)有合并優(yōu)化以及節(jié)點(diǎn)的虛函數(shù)調(diào)用對(duì)于CPU Cache非常不優(yōu)化,導(dǎo)致傳統(tǒng)的SQL引擎計(jì)算性能比較差。右側(cè)為T(mén)ungsten優(yōu)化后的結(jié)果,使用了whole staged code generation,對(duì)多節(jié)點(diǎn)的循環(huán)進(jìn)行了合并,性能有著明顯的提升。
2. Catalyst/Tungsten的不足
Catalyst/Tungsten給Spark帶來(lái)了明顯的性能能提升,但Catalyst/Tungsten的優(yōu)化仍然是基于Java進(jìn)行的,如果能使用更底層的指令集,如匯編、二進(jìn)制碼效果會(huì)更好;JVM難以支持循環(huán)展開(kāi)等優(yōu)化方式;而且并非所有的節(jié)點(diǎn)都支持code generation,例如圖中的WindowExec節(jié)點(diǎn)就不支持code generation。
3. FESQL
鑒于以原因,Catalyst/Tungsten的優(yōu)化仍有不足,第四范式基于LLVM技術(shù)進(jìn)一步優(yōu)化得到FESQL。SparkSQL架構(gòu)如黃色部分所示,F(xiàn)ESQL架構(gòu)如藍(lán)色框所示,根據(jù)SparkSQL語(yǔ)句生成FESQL Logical Plan,再由LLVM JIT生成平臺(tái)二進(jìn)制碼直接執(zhí)行,相比于Spark少了JVM一層,性能也會(huì)有明顯提升。
4. LLVM簡(jiǎn)介
LLVM項(xiàng)目是一個(gè)模塊化的、可重用的編譯器和工具鏈集合,可以方便的實(shí)現(xiàn)編譯器和代碼生成的工作。提供了許多有用的工具,如Clang、LLDB、MLIR、TVM等,能夠?qū)崿F(xiàn)多種編程語(yǔ)言的編譯器。
JIT ( Just-In-Time Compiler ) 編譯,可以一邊運(yùn)行程序一邊編譯二進(jìn)制代碼,右圖為使用JIT編譯的Add函數(shù),這部分代碼可以在運(yùn)行時(shí)被翻譯成底層代碼,與直接使用C++來(lái)實(shí)現(xiàn)效率接近,同時(shí)JIT能夠適應(yīng)不同的CPU生成優(yōu)化的二進(jìn)制碼。
5. FESQL的優(yōu)化點(diǎn)
目前已經(jīng)能使用循環(huán)展開(kāi)、常數(shù)折疊、向量化和一些基于CPU本身的優(yōu)化;未來(lái),基于PTX后端還可以嘗試生成CUDA代碼,利用GPU進(jìn)行計(jì)算的加速。
6. 性能比較
FESQL與Databrick內(nèi)部的Photon非常相似 ( Photon內(nèi)部由C++實(shí)現(xiàn) ),因而進(jìn)行對(duì)兩者進(jìn)行比較。Photon是Databrick的企業(yè)產(chǎn)品,僅能在Databrick的平臺(tái)上使用,且不支持PTX/CUDA。對(duì)比由C++和由JVM實(shí)現(xiàn)的處理引擎的性能,發(fā)現(xiàn)C++實(shí)現(xiàn)的處理引擎性能非常優(yōu)越。
7. FESQL的節(jié)點(diǎn)優(yōu)化
FESQL使用了節(jié)點(diǎn)優(yōu)化,使用SimpleProject對(duì)Project節(jié)點(diǎn)進(jìn)行合并優(yōu)化,對(duì)窗口節(jié)點(diǎn)使用code generate進(jìn)行優(yōu)化。下圖說(shuō)明了對(duì)于節(jié)點(diǎn)的優(yōu)化可以明顯減少執(zhí)行的流程。
8. FESQL的表達(dá)式優(yōu)化
FESQL也實(shí)現(xiàn)了非常多表達(dá)式優(yōu)化,保證在不同SQL場(chǎng)景都比傳統(tǒng)數(shù)據(jù)庫(kù)有著更好的性能表現(xiàn)。
9. 性能
對(duì)比Spark 3.0和FESQL on Spark可以發(fā)現(xiàn),F(xiàn)ESQL的執(zhí)行效率明顯高于Spark 3.0,多窗口的情況下效果更明顯,有著接近6倍的性能提升。
通過(guò)對(duì)比兩者生成的邏輯計(jì)劃圖,可以發(fā)現(xiàn)FESQL的計(jì)劃圖明顯更簡(jiǎn)單,通過(guò)對(duì)比兩者的火焰圖,底層RDD計(jì)算基本一致,F(xiàn)ESQL取樣的樣本數(shù)更少,執(zhí)行時(shí)間更短,因此FESQL的執(zhí)行效率更高。
10. 展望
未來(lái)第四范式計(jì)劃推出LLVM-enabled Spark Distribution,使開(kāi)發(fā)者可以通過(guò)設(shè)置SPARK_HOME便利的實(shí)現(xiàn)性能加速;為開(kāi)發(fā)者提供Docker、Notebook、Jar、Whl包,便于開(kāi)發(fā);提供類似Python的保證一致性的DSL語(yǔ)言用于UDF和UDFA實(shí)現(xiàn);還有提供對(duì)CUDA和GPU的支持。
大規(guī)模推薦系統(tǒng)中可以使用Spark、Flink、ES、FESQL實(shí)現(xiàn)大規(guī)模的數(shù)據(jù)處理,其中Spark更適合離線的批處理,而不適合線上處理,F(xiàn)ESQL能同時(shí)進(jìn)行線上線下服務(wù)因?yàn)槟軌虮WC特征一致性,同時(shí)LLVM JIT實(shí)現(xiàn)的FESQL擁有比Spark 3.0更好的性能。
更多SQL原生計(jì)算引擎以及Spark性能優(yōu)化的技術(shù),歡迎關(guān)注我們后續(xù)的分享。今天的分享就到這里,謝謝大家。
嘉賓介紹:
陳迪豪
特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:
長(zhǎng)按訂閱更多精彩▼
如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!