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