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