浅谈 Spark 的多语言支持
作者:鄭鍇,花名鐵杰,阿里巴巴高級(jí)技術(shù)專(zhuān)家,Apache Hadoop PMC,Apache Kerby 創(chuàng)立者。深耕分布式系統(tǒng)開(kāi)發(fā)和開(kāi)源大數(shù)據(jù)多年,先后專(zhuān)注在安全,存儲(chǔ)和計(jì)算領(lǐng)域。之前在 Intel,目前轉(zhuǎn)戰(zhàn)阿里云上,致力于提供更好用更有彈性的 Hadoop/Spark 大數(shù)據(jù)平臺(tái)。
Spark架構(gòu)和設(shè)計(jì)上的優(yōu)秀毋庸置疑,從一出道便搶了 Hadoop 的 C 位。在開(kāi)源大數(shù)據(jù)的黃金十年一時(shí)風(fēng)頭無(wú)兩,在當(dāng)下人工智能時(shí)代仍然能夠與時(shí)俱進(jìn),通天之處不遑多言,美中不足之處也有不少。小的方面,比如調(diào)度模型跟 MapReduce 這種計(jì)算范式過(guò)于耦合,Spark 最近引入 Barrier 調(diào)度模式就是為了支持深度學(xué)習(xí)這種新的計(jì)算類(lèi)型,所幸在于對(duì)框架的改動(dòng)不會(huì)傷筋動(dòng)骨;有些缺陷則不然,影響全局,調(diào)整起來(lái)絕非易事。今天我主要想談下 Spark 的框架語(yǔ)言實(shí)現(xiàn)和多語(yǔ)言支持---------有得,必有失。
Spark 核心和框架構(gòu)建在 Scala 上,對(duì)應(yīng)用開(kāi)發(fā)者也是言必稱(chēng) Scala,直接秀起了代碼極簡(jiǎn)的肌肉。在用戶(hù)接口上,從企業(yè)級(jí)應(yīng)用的首選 Java,到數(shù)據(jù)科學(xué)家的 Python 和 R,再到商業(yè)智能 BI 的 SQL,官方都一一支持,按說(shuō)已經(jīng)很全面很完整了,各方神圣也都伺候到了,還有什么抱怨的,言何缺陷?首先,對(duì) Python 的支持也就是 PySpark ,復(fù)雜且效率低下,有點(diǎn)像 hack,十分像早期 Spark 攻城略地的產(chǎn)出。其實(shí)對(duì) R 的支持 SparkR 也如出一轍,我們討論清楚了 PySpark 也就明白了對(duì)其他語(yǔ)言的支持其實(shí)是類(lèi)似的。從使用者的角度來(lái)看用 PySpark 寫(xiě)程序的體驗(yàn)還是很不錯(cuò)的,跟 Scala 有點(diǎn)類(lèi)似,簡(jiǎn)潔而優(yōu)雅,就跟寫(xiě)個(gè)單機(jī)程序一樣,不需要考慮分布式處理的復(fù)雜性。然而在這件漂亮的外衣下,用 PySpark 寫(xiě)的 Spark 程序就是比 Scala 版本慢,還動(dòng)不動(dòng) OOM 掉,為什么?我們來(lái)探一下究竟。
一般 Spark 程序首先給定輸入也就是要處理的數(shù)據(jù)集,然后表達(dá)好針對(duì)這個(gè)數(shù)據(jù)集的每行記錄要處理的邏輯和轉(zhuǎn)換規(guī)則,再將結(jié)果打印出來(lái)或是保存到文件。背后 Spark 框架進(jìn)行翻譯轉(zhuǎn)換,產(chǎn)出一個(gè)個(gè) RDD 和這些 RDD 之間的關(guān)系,每個(gè) RDD 表示對(duì)應(yīng)的數(shù)據(jù)集和在該數(shù)據(jù)集上要執(zhí)行的變換處理邏輯。這些 RDD 根據(jù)它們之間的依賴(lài)關(guān)系組成 DAG,對(duì) DAG 翻譯轉(zhuǎn)換成 stages 和 tasks,這個(gè)過(guò)程在 driver 端由框架 Scala 代碼完成,包括對(duì) stages 和 tasks 的調(diào)度執(zhí)行;RDD 的處理邏輯對(duì)應(yīng)用戶(hù)的 Scala 或 Python 代碼,因?yàn)橐植际讲l(fā)處理,主要在 executor 上執(zhí)行。因此,對(duì)于 Python 版本的 Spark 程序,在 driver 上和 executor 上都有要執(zhí)行的 Python 代碼,必然需要對(duì)應(yīng)的 Python 解釋器來(lái)執(zhí)行;然而 Spark 計(jì)算框架是 Scala/Java 代碼實(shí)現(xiàn)的,driver 和 executor 整體上得跑在 JVM 進(jìn)程里面。那么如何在 driver 端和 executor 上同時(shí)執(zhí)行代表用戶(hù)邏輯的 Python 代碼和核心引擎的 JVM 代碼,并在兩者之間進(jìn)行交互和協(xié)調(diào)呢?
PySpark 的做法是在 driver 端和 executor 上伴隨必需的 JVM 進(jìn)程,再 launch 起來(lái)單獨(dú)的 Python 解釋執(zhí)行進(jìn)程,然后通過(guò) socket,文件和 pipeline 進(jìn)行交互和協(xié)作。這是個(gè)非常低效的做法,因?yàn)?Spark 程序通常不會(huì)應(yīng)用在一個(gè)普通場(chǎng)景里,而是要處理非常大的數(shù)據(jù)集。對(duì)于成千上萬(wàn)行記錄的處理,都要在 executor 上通過(guò)跨進(jìn)程管道到 Python 進(jìn)程上來(lái)回一趟,末了在 driver 上,為了傳遞計(jì)算結(jié)果可能還要寫(xiě)個(gè)磁盤(pán)文件才能轉(zhuǎn)給 Python 進(jìn)程,為此涉及到大量記錄數(shù)據(jù)在 Python 和 Java 之間要序列化和反序列化,效率可想而知。開(kāi)啟新的 Python 進(jìn)程直接執(zhí)行用戶(hù)的代碼省事倒是省事,但是除了效率問(wèn)題,還要考慮到進(jìn)程管理、內(nèi)存控制、容器環(huán)境和數(shù)據(jù)安全,這樣做的代價(jià)還是很大的,然而 Spark 卻不得不這樣做,主要是因?yàn)槭芟抻谒谡Z(yǔ)言支持上面缺乏長(zhǎng)遠(yuǎn)的考慮和整體的設(shè)計(jì),這就是我想講的最重要的問(wèn)題。
在語(yǔ)言支持上,從一開(kāi)始 Spark 的關(guān)注點(diǎn)就是“糖衣”而非“炮彈”,在用戶(hù)體驗(yàn)上追求數(shù)據(jù)處理邏輯表達(dá)的簡(jiǎn)潔有力,因此完勝當(dāng)時(shí)的各種計(jì)算框架而后一騎絕塵。記得在 Hadoop 如日中天的時(shí)候,筆者所在的 Intel 大數(shù)據(jù)團(tuán)隊(duì)正在玩 Hadoop 不亦樂(lè)乎,Spark 的作者 Matei 先生在遠(yuǎn)程會(huì)議上向我們演示當(dāng)時(shí)還十分稚嫩的 Spark,看到那個(gè)有名的 MapReduce Helloworld 例子 WordCount 程序只需要幾行 Scala 代碼搞定,真是駭人。Spark 能夠在短時(shí)間內(nèi)搶了 Hadoop 的風(fēng)頭,除了性能更快,毫無(wú)疑問(wèn)這也是個(gè)關(guān)鍵因素。然而這種簡(jiǎn)潔有力,在多大程度上要?dú)w功于 Scala,其實(shí)不太好講。最本質(zhì)的還是在于 RDD 本身的抽象,豐富的算子支持和巧妙的關(guān)系推導(dǎo),這部分可以歸為引擎層面,大體上用其他語(yǔ)言,比如更擅長(zhǎng)做系統(tǒng)框架的,比如 C++,也能實(shí)現(xiàn)。至于用戶(hù)的程序是用 Scala 還是 Python,只要支持 closures,應(yīng)該都能行,簡(jiǎn)潔程度上不會(huì)差別太大,也完全可以多支持一些語(yǔ)言,每個(gè)用戶(hù)具體用哪一個(gè)要看個(gè)人的偏好,沒(méi)有道理讓大家都去學(xué)一個(gè)新的語(yǔ)言.
可惜的是,Spark 引擎的實(shí)現(xiàn)應(yīng)該是受到了主要用戶(hù)接口語(yǔ)言 Scala 的影響,也采用了 Scala,部分采用 Java,但本質(zhì)上都是 JVM 語(yǔ)言,這樣做的好處是一鍋煮,省事。考古學(xué)家可以列出一大堆使用 Scala 的好處,比如代碼行數(shù)少,codegen 給力之類(lèi)的,但是這些都是局部的,從整體上 Spark 作為一個(gè)統(tǒng)一的大數(shù)據(jù)處理平臺(tái),其實(shí)更需要長(zhǎng)遠(yuǎn)的通盤(pán)考慮。這個(gè)考慮就是在用戶(hù)接口上要能夠更快更好地支持更多的用戶(hù)語(yǔ)言,在計(jì)算引擎上能夠支持硬件層面的極致性能優(yōu)化,在計(jì)算場(chǎng)景上也能支持其他計(jì)算引擎的集成。
這個(gè)考慮簡(jiǎn)單來(lái)說(shuō)就是缺乏對(duì)框架層面的 C/C++ 支持。當(dāng)然這個(gè)支持很難在第一天就考慮進(jìn)來(lái),畢竟關(guān)注點(diǎn)不在這兒,那個(gè)時(shí)候估計(jì) Matei 先生也想不到 Spark 會(huì)這么成功。然而框架層面缺乏對(duì) C/C++ 的原生支持或者換句話(huà)說(shuō),框架核心沒(méi)有采用 C/C++ 這種 native 語(yǔ)言來(lái)開(kāi)發(fā),其弊端和對(duì) Spark 今后長(zhǎng)遠(yuǎn)發(fā)展的影響毫無(wú)疑問(wèn)顯而易見(jiàn)。C/C++ 作為系統(tǒng)語(yǔ)言,下可以跟硬件直接打交道,上可以直接對(duì)接各種開(kāi)發(fā)語(yǔ)言,因此也不難支持各種計(jì)算處理庫(kù)和引擎。Spark 本身定位為一個(gè)大數(shù)據(jù)處理平臺(tái),如果核心公共邏輯和操作交給 C/C++ 來(lái)實(shí)現(xiàn),那么首先支持 Python 這種用戶(hù)接口語(yǔ)言,直接利用 FFI 機(jī)制調(diào)用就是了,簡(jiǎn)單且無(wú)損效率。主流的開(kāi)發(fā)語(yǔ)言基本上都很好地支持 C/C++和Python ,像 Java,Go,Rust,Julia······。Spark 添加一個(gè)新的語(yǔ)言支持,就簡(jiǎn)化為添加一個(gè)新的 binding,還好維護(hù),也不用擔(dān)心這個(gè)功能被閹割,那個(gè)支持還不全。對(duì)新的硬件做優(yōu)化也不成問(wèn)題,比如從計(jì)算新貴 GPU 到 RDMA,再到可持久化大內(nèi)存 AEP,根本不會(huì)受限于 JVM 的限制,各大硬件廠商都能自己擼起袖子開(kāi)搞,Spark 坐享其成就是。現(xiàn)在對(duì)這些新硬件的支持為什么上不了,社區(qū)不接受?主要還是缺乏框架層面的支持,搞出來(lái)的都像是 hack,進(jìn)去也是麻煩。看看人家 Tensorflow 就知道了,CPU,TPU,GPU 都能玩得轉(zhuǎn),否則跟不上來(lái)遲早面臨淘汰。
核心框架采用 Scala/Java 來(lái)實(shí)現(xiàn),還有一個(gè)重要的影響是數(shù)據(jù)集的內(nèi)存表示,早期 Spark 直接用 Java 對(duì)象來(lái)表示數(shù)據(jù)記錄,需要持久化或者網(wǎng)絡(luò)傳輸要序列化和反序列化,當(dāng)然在這一點(diǎn)上 Spark 后來(lái)很快意識(shí)到了問(wèn)題,通過(guò) offheap 和 Tunsten 項(xiàng)目馬上把問(wèn)題解了,所幸還有招數(shù)。如果是 C/C++ 實(shí)現(xiàn)的,數(shù)據(jù)的內(nèi)存布局必然會(huì)采取類(lèi)似 Arrow 的這種中性表示,方便各種用戶(hù)接口語(yǔ)言來(lái)訪問(wèn)和操作,就像深度學(xué)習(xí)框架里面常見(jiàn)的 tensor,必須考慮高效傳遞。
最后一點(diǎn),采用 Scala/Java 來(lái)實(shí)現(xiàn)的 Spark 框架,雖然整合企業(yè)級(jí)應(yīng)用里面很常見(jiàn)的各種數(shù)據(jù)源得心應(yīng)手,但要整合集成更多的計(jì)算框架則就力不從心了。類(lèi)似于對(duì)新硬件的支持,看一下 Yahoo 對(duì) Caffe 和 Tensorflow 的支持就明白了,只能 hack 一下自己玩,不可能融入到 Spark 里面流行起來(lái),要原生支持 deep learning,像 machine learning,可以,但要自己擼。Spark 自己花了很大力氣搞 mllib,Intel 搞 BigDL,都是沒(méi)辦法,因?yàn)槿狈诵目蚣艿慕o力支持,不能直接把這些領(lǐng)域里面現(xiàn)成的庫(kù)實(shí)現(xiàn)和計(jì)算引擎集成進(jìn)來(lái)。如果核心框架是是 C/C++ 實(shí)現(xiàn)的,集成 PyTorch 和 Tensorflow 能有多大的問(wèn)題?無(wú)非是多掛一個(gè)動(dòng)態(tài)模塊或搞一個(gè)插件的事情。
好吧,啰嗦到這兒,問(wèn)題有解嗎?肯定有。Spark 搞定了用戶(hù)生態(tài),只要保持接口兼容不變,核心框架來(lái)個(gè)天翻地覆,改弦更張換個(gè)語(yǔ)言來(lái)實(shí)現(xiàn),未嘗不可,就看有沒(méi)有人愿意這么干。有沒(méi)有更取巧的辦法呢,不用聽(tīng)起來(lái)這么嚇人?答案也是肯定的,筆者所在的團(tuán)隊(duì)就在干這樣的事情,阿里巴巴計(jì)算平臺(tái),開(kāi)源大數(shù)據(jù)部門(mén) EMR,致力于在云上打造極致的彈性 Spark 計(jì)算體驗(yàn),做會(huì)在云上玩的 Spark,歡迎了解。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的浅谈 Spark 的多语言支持的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 飞天2.0 | 万物智能的基础服务
- 下一篇: AutoML数据增广