基於LLVM的內存計算

2021-01-15 CSDN技術社區

最近業界有很多技術和產品都被認為屬於內存計算的範疇,並且大家都覺得內存計算是未來大數據方面的核心技術,特別是類似Spark和HANA這樣的產品和技術湧現,使得內存計算已經在大數據技術方面成為主流。但身為一個在內存計算方面研究3年左右的筆者,感覺很多人對於內存計算的理解僅停留在把數據緩存在內存中,或者使用最新的SIMD指令集,但筆者在這三年的研發過程中的最大發現並不是這樣,我個人覺得內存計算引擎相對於傳統數據處理引擎,最大的革新是基於LLVM編譯器的動態代碼生成技術,所以本文將給大家介紹現在的產品和技術是如何使用LLVM編譯器來動態生成執行代碼的,從而實現真正意義上的內存計算,那麼在深入這個技術之前,想給大家稍微介紹一下LLVM的技術本身。

LLVM-移動時代的幕後英雄

LLVM是Low Level Virtual Machine的簡稱,首先,大家不要被這個名字所誤導,認為它是類似VMware和KVM這樣的虛擬機項目,其實它是一個類似GCC的大型編譯器框架。而LLVM這個名字本身隨著這個項目不斷發展,已經無法完全代表這個項目了,只是作為這種叫法一直延續下來。

作為編譯器,LLVM本身和GCC一樣,是一個開源的項目,協議是BSD,而不是Linux和GCC所用的GPL協議。它最早的時候是伊利諾伊大學厄巴納香檳分校的一個研究項目,主要負責人是大牛Chris Lattner,並且項目本身也很榮幸地獲得2012年ACM軟體系統獎。

LLVM可以作為多種語言的後端,它可以提供可程式語言無關的優化和針對很多種CPU的代碼生成功能,與GCC相比,它的整體架構更清晰,速度更快,此外,LLVM已經不僅僅是個編程框架,它目前還包含了很多子項目,比如最具盛名的用於C編譯的Clang,除此之外,還有用於連結GCC前端解析器的Dragonegg等項目。

雖然LLVM對於很多程式設計師而言是一個陌生的名詞,但是在整個移動時代起到了至關重要的作用,無論是Android還是iOS平臺。

對於iOS平臺而言,Chris Latter現在就職於Apple,而且Apple目前也是LLVM主要贊助者之一。在iOS之前,LLVM的誕生就給OSX本身的開發帶來極大的幫助,因為當時Apple困於GCC無法提供給他們完善的支持,特別是和Object-C相關的編譯部分,而當時LLVM項目的出現幫助他們解決燃眉之急,包括後面Grand Dispatch這樣的核心功能都有LLVM的影子。到了iOS時代,LLVM已經是整個iOS平臺最底層的核心,無論從iOS系統本身的編譯,以及XCode的調試支持,還是最新的語言Swift也都是由LLVM之父Chris Latter本人設計的。

儘管Android平臺是iOS平臺的對手,但Android平臺對LLVM依賴更盛,雖然4.4之前都是用自建的Dalvik VM,使用類似JIT(Just-in-time Compiler)這樣即時編譯的形式來執行,但是在性能和用戶體驗方面被大家所詬病,所以在Android的4.4版本推出了ART模式,ART是直接使用LLVM去做AOT(Ahead of Time)編譯,也就是在安裝的時候直接將程序編譯為機器碼,平時Android用戶使用App的時候能像iOS用戶一樣直接執行本地代碼,這樣使Android的整體性能已經接近iOS的水準,雖然在安裝的時候,可能需要多花點時間用於做預編譯。所以LLVM可謂是移動時代的幕後英雄,那麼它和傳統的數據處理有什麼關係呢?在深入介紹LLVM是如何改變傳統數據處理引擎之前,讓我們先了解一下傳統數據處理引擎的短板。

傳統數據處理引擎的短板

眾所周知,最初傳統數據處理引擎(比如Postgres,Oracle等)的主要瓶頸在於I/O,因為當時底層硬碟的速度實在乏善可陳,多年沒有進步,但是隨著近幾年多節點並行,SSD,大內存等I/O資源的發展,更重要的是列存技術的普及和進化,使得I/O問題已經不再是一個極大的瓶頸,但隨之而來的就是在網絡和CPU方面的瓶頸反而顯現出來,由於網絡瓶頸不是本文關注的重點,所以主要聊聊數據處理引擎CPU方面的瓶頸。


圖1 繁瑣的數據處理引擎代碼

雖然新一代基於內存的計算引擎,使得I/O性能比傳統基於硬碟有10倍左右的性能提升,但與之同時,CPU的瓶頸會更明顯,基於我們之前測試結果,以傳統Postgres的引擎為例,操作數據都被緩存到內存的Page Cache上面,它做最簡單的Count(*)統計都只能勉強達到每秒鐘400萬行左右,而真實所需要的操作其實是很少的,按照2010年的X86 CPU而言,其實處理這些計算是非常簡單的,但實際性能還是很低,為什麼呢?在這裡,先和大家聊聊現在X86 CPU性能特徵,隨著技術本身的發展,X86 CPU本身的處理能力非常強大,但是一切換Context就會出現性能方面的小滑坡。如果等待處理的命令和數據沒有被預緩存在Cache上面,而是需要訪問的內存的話,會有一個更大的性能滑坡。既然大家都了解CPU本身的瓶頸,下面來聊聊傳統資料庫處理引引擎的短板有哪些?主要有以下四點:

其一是條件邏輯冗餘,數據處理引擎代碼非常繁瑣,因為SQL語句本身非常複雜,所以數據引擎為了支持那些複雜的SQL語句,使得數據處理引擎需要複雜的條件邏輯來處理,就像圖1那樣,甚至一個Switch循環裡面會有成百上千的case這樣的選擇邏輯,雖然Switch循環本身會被編譯器進行一定程度的優化,但是最終機器碼中的分支指令會一定程度上阻止指令的管道化(instruction pipelining)和並行執行(instruction-level parallelism)。

其二是虛函數的調用,和第一個問題的原因類似,因為數據處理引擎要支持極為複雜的SQL語句,還有十幾種的數據類型,比如,程序在處理add這個邏輯的時候,此時數據處理引擎需要根據來源數據是INT還是BIGINT來選擇不同的函數來處理,所以在實際處理時,肯定只能用虛函數來轉給具體的執行函數,這個對CPU的影響肯定是非常明顯的,因為很多時候虛函數調用本身的運行成本,比這個函數本身執行成本更高。更因為如此,內聯函數這個最常見的性能優化方式也無法被使用。

其三是需要不斷地從內存中調用數據,而無法一次性將數據從內存加載至Cache上,比如,常見的For循環,雖然知道下一個數據就在下一個偏移地址,但還是要從內存上面讀取,這樣讀取開銷很大而且阻止整個CPU管道化的操作。

其四是因為不同x86 CPU年代不同,所以支持不同擴展指令集,而這些新的指令集對很多操作都能提升100%以上的性能,比如,有些比較新的CPU支持SSE 4.2,而有些卻不支持,為了保證數據引擎能跨不同的硬體平臺,所以數據引擎很少支持一些擴展的指令集,這導致浪費了本來可以提升的性能沒有得到支持。

雖然這些瓶頸很難克服,但Google研發的Tenzing技術裡面提出基於LLVM編譯框架實現動態生成代碼Codegen這個技術,並且通過這個技術基於MapReduce分布式框架下面的類SQL系統的性能也能接近商業收費並行資料庫的水準。Codegen這種方式,就是在SQL執行前才編譯具體的執行代碼,之前的數據引擎本身是一個大而複雜的框架,任何計算包括1+1,都要進入這個龐大的框架裡面做判斷來選擇合適的函數來執行1+1,所以最終的成本就像前面列的那樣,是非常高的。那麼使用Codegen的好處如下:

其一是簡化了條件分支,因為在生成代碼的時候,程序已經獲知運行時的信息,通過展開for循環(因為我們已經知道循環次數)和解析數據類型,所以可以像圖2那樣if/switch這些分支指令這樣的語句就能優化掉,這是非常簡單有效的。


圖2 if/switch分支指令語句

其二是內存加載,我們可以使用代碼生成來替代數據加載,這樣極大減少內存的讀取,增加CPU Cache的利用率,這對CPU性能而言非常有幫助。


圖3 用代碼生成取代虛函數的調用

其三是內聯虛函數的調用,因此當對象實例的類型在運行時可知,我們可以如圖3所示使用代碼生成來取代虛函數的調用,並做內聯化,這樣表達式可以無需函數調用而直接求值。此外,內聯後的函數使編譯器做進一步的優化,例如子表達式消除等。

其四是能利用最新的指令集,在Codegen的時候,由於Codegen本身是在即將執行的那個節點執行,所以它很方便就能感知到其底層CPU到底支持那個版本最新的指令集,比如是SSE 4.2還是SSE4.1,所以Codegen完全會根據具體的指令集支持來編譯具體的執行代碼,使其能儘可能地利用最新的指令集。


圖4 基於TPCH-Q1的基準測試

基於圖4的測試結果(跑TPCH-Q1,數據量2.7GB,單節點,Codegen時間150ms),通過這樣的Codegen方式的確能有效地提升數據處理引擎利用CPU的效率,整體性能提升達到3倍以上,並且Cache Miss率和之前比重大提升。當然Codegen技術就像其他技術一樣,它也有自己的成本和不足,那就是在Codegen本身的代碼生成操作也是需要一定的時間,包括For循環展開和多層次pass優化,雖然LLVM本身的處理性能強,但是這樣操作還是很耗時,一般都要100-200ms左右,但原本一個10秒鐘的查詢卻因次提升到了6秒,我相信大家都能理解。

基於LLVM的動態代碼生成技術

業界已經有越來越多的內存計算產品採用基於LLVM的動態代碼生成技術,已經有成為內存計算標配的趨勢,除了上面提到在Google內部大範圍使用的Tenzing外,還有Cloudera Impala和SAP HANA也在使用Codegen技術,另外內存領域當紅的Spark,也計劃在接下來的版本中實現Codegen。

Cloudera Impala的實現方式

雖然Cloudera Impala在業界毀譽參半,貌似現在在Cloudera內部也準備放棄Impala,改方向往Spark發展,但是Impala在性能方面還是很受到大家的認可,主要原因就是其使用基於LLVM的動態代碼生成技術。為什麼採用Codegen?除了性能好之外,另一個因素就是Impala的首席設計師本身就是Google Tenzing的設計師。

那麼讓我們看看Cloudera Impala的具體實現方式。由於在運行時候將執行邏輯代碼動態生成機器代碼,成本會很高,所以Impala在編譯的時候,會先將具體的一些執行函數先編譯成LLVM的IR(Intermediate Representation)這個中間形態,從而生成一個大的IR文件,裡面包括所有相關函數的IR代碼塊,之後在具體SQL命令執行開始之前,數據節點DataNode會先根據具體的SQL語句,從根節點開始遞歸初始化執行樹(AST),之後開始LLVM會根據執行樹來調用那個IR文件裡面對應函數的IR代碼塊來生成本地可執行代碼,接著會繼續對生成好的代碼進行優化來進一步提升性能。

SAP HANA的設計思路

其實至少十年前就有一波內存計算的風潮,那時企業級產品中,具代表性的主要有用於OLTP事務加速的Timeten和Altibase,而2010年開始推廣的那些內存計算技術產品中,最有代表性的莫過於SAP的HANA。

SAP HANA在處理邏輯上,全面採用向量計算(Vector Processing)的理念,儘可能地使用最新的SSE4.1和SSE4.2等指令集,還有就是在多核NUMA場景下降低運行消耗,使其多線程性能提升比儘可能地接近1。另外,在數據結構方面,為了儘可能地利用CPU緩存(Cache),並儘可能減少訪問內存,所以推出了緩存敏感的CSB(Cache Sensitive B+)樹來代替傳統的B樹。

為了進步提升,並且完善整體架構和提升性能,HANA也使用了LLVM支持動態編譯,無論是SQL查詢還是MDX(Multi-Dimensional Expressions,多維表達式)查詢等,在HANA內部都會都被轉譯一個公共的表示層,名為L語言,並且在執行之前,會使用LLVM編譯為二進位代碼並直接執行,這樣做的好處是避免傳統資料庫引擎裡面繁瑣邏輯,從而提升性能,並且這樣L語言的形式,對於HANA今後添加更多的功能非常有幫助,所以HANA在很短的時間內支持很多SQL分析語句之後,還支持各種數據挖掘的算法,還提供很多定製化腳本,讓用戶根據自己的業務需求來擴展HANA的功能。

Apache Spark的設計思路

大家都知道,現在Apache Spark可以說是最近最火的開源大數據項目,就連EMC旗下專門做大數據Pivotal公司也開始準備拋棄其自研十幾年GreenPlum技術,轉而投入到Spark技術研發當中。並且從整個業界來看,Spark火的程度也只有IaaS界的OpenStack能相提並論。那麼我們接著就直接切入它的核心機制吧。

Spark已經將代碼生成用於SQL和DataFrames裡的表達式求值(expression evaluation),同時他們正準備努力讓代碼生成可以應用到所有的內置表達式上,並且在這個基礎上支持更多新指令集。還有他們不僅通過Codegen內部組件來提升CPU效率,還期望將代碼生成推到更廣泛的地方,比如,數據的序列化,也就是Shuffle數據再分布的過程中,將數據從內存二進位格式轉換到wire-protocol這樣流格式的過程,因為Shuffle通常會因數據系列化而出現性能瓶頸,而通過代碼生成,可以顯著地提升序列化吞吐量,從而反過來作用到shuffle網絡吞吐量的提升。


圖5 shuffle性能分析

圖5對比了單線程對800萬複雜行做shuffle的性能,分別使用的是之前Kryo方式和最新代碼生成,在速度上後者是前者的2倍以上。

最後,筆者覺得這個技術所帶來在內存計算部分的效應只能說是整個蝴蝶效應最開始的那部分,今後對整個雲計算會帶來更多的變革。你能想像中間件和資料庫合二為一嗎?你能想像所有的業務代碼和基礎設施代碼都動態生成嗎?你能想像當整個百萬臺雲計算集群被合併為一個大電腦的時候,數據和命令都合二為一嗎?而這些就是我認為LLVM給我們帶來的巨大變革,而我們中國人在這場浪潮中應該起著領導的角色。

作者:吳朱華

簡介:上海雲人信息科技有限公司聯合創始人兼CEO,國內資深的雲計算和大數據專家,之前曾在IBM中國研究院參與過多款雲計算產品的開發工作。2010年底,他和另兩位創始人組建了一支十多人的團隊,在上海楊浦雲基地辦公。

本文為CSDN原創文章,未經允許不得轉載,如需轉載請聯繫market#csdn.net(#換成@)

相關焦點

  • llvm學習第二站 - 什麼是llvm IR
    官網介紹:https://releases.llvm.org/11.0.0/docs/GettingStarted.html工具名稱工具用途llvm-ar‍歸檔器,創建靜態庫,用法和ar基本一致llvm-asLLVM assembler 彙編器,輸入是LLVM IR,輸出為
  • FEKO計算中減少內存的方法
    用FEKO軟體進行電磁仿真時,由於電磁仿真對計算資源的強烈需求,計算資源尤其是內存的大小極大的成為決定求解問題規模的約束條件。為了在已有的硬體計算條件下,解決儘量大的電磁問題,FEKO提供了一些減少內存的途徑,主要可分為二個層面,其一是算法層面的節約內存,其二是技巧層面的節約內存。本文引用地址:http://www.eepw.com.cn/article/259796.htm算法從算法上面來講,FEKO提供的有MoM,MLFMM,PO,UTD,FEM。
  • Oracle Database In-Memory:重新定義內存計算?
    提到內存計算,就不能不提最近幾年大紅大紫的SAP公司,其HANA內存計算解決方案賺足了市場的眼球,在短短幾年時間擁有超過幾百家的用戶,並獲得了包括IBM、HP、Dell、華為等伺服器廠商的大力追捧。與此同時,不能否認的是類似SAP HANA這樣動輒上百萬美金的內存計算解決方案依然只是少數經濟實力雄厚的用戶的選擇。
  • 模擬內存計算如何解決邊緣AI推理的功耗挑戰
    這在傳統的數字神經網絡實現中是很難做到的,在這種情況下,內存成為了耗電的瓶頸。這個問題可以通過多層內存和使用模擬內存計算方法來解決,這些計算方法可讓處理引擎能夠滿足在網絡邊緣執行人工智慧推斷所需的更低的毫瓦到微瓦的功率要求。
  • 通過LLVM 在 Android 上運行 Swift 代碼
    Swift 編譯器這都是由 Chris Lattner 設計的,很容易就可以發現 Swift 的編譯器是基於 LLVM 構建的。LLVM 是個編譯器基礎設施,利用了了一個可重定向編譯器的有趣概念。同時也要求其他 symbols,主要是為了處理字符串轉換和內存處理。無論如何,所有這些 symbols 已經在 libswiftCore.dylib 定義,也出現在 $SDK。
  • 伏羲聯合實驗室新成果 平安雲-浪潮推出基於英特爾傲騰持久內存的...
    2018年12月,浪潮與平安雲建立「伏羲」聯合實驗室,基於計算技術與應用場景的融合,共同為客戶提供領先的雲創新產品,此次推出的基於傲騰持久內存的Redis雲服務就是聯合實驗室發布的最新成果。為什麼選擇推出基於英特爾傲騰持久內存的Redis雲服務?任何一種技術與商業變現的關聯越明顯,就越能凸顯技術的價值。
  • 回顧:神經擬態計算需求下的6種新內存技術
    【IT168 技術】對神經擬態計算的興趣促使人們去研究一種新的內存設備,以複製/實現生物神經元和突觸的特性功能。近日有一篇論文(https://onlinelibrary.wiley.com/doi/10.1002/admt.201800589)回顧了該領域的現狀,並討論了6種在這一領域最有前途的技術。
  • 終結硬碟時代 主流內存資料庫對比報告
    在這種情況下,主內存資料庫缺乏對ACID中持久性(Durability)的支持。基於非永久性存儲的主內存資料庫通常情況下能夠支持其他三種ACID屬性,即原子性(Atomicity)、一致性(Consistency)和隔離性(Isolation)。
  • 基於3D憶阻器的電路,用於大腦啟發式計算
    「以前,我們開發了一種非常可靠的憶阻設備,可以滿足人工神經網絡的內存計算的大多數要求,將這些設備集成到大型二維陣列中,並展示了多種機器智能應用,」進行這項研究的Qiangfei Xia教授說,「在我們最近的研究中,我們決定將其擴展到第三維,探索3-D神經網絡中豐富的連接的好處。」
  • 基於NETFPGA的可重構科學計算平臺
    本項目的研究目標是探索和建立圖形化數學算法向硬體轉換的理論方法,研究開發數學算法向硬體邏輯轉換的工具,與科學計算軟體相結合建立起基於FPGA陣列的科學計算平臺原型。研究目標結構流程如下:目前,可重構計算已有較大發展,主要目標是希望通過硬體可編程,來自適應計算任務的需求,以期達到最佳性能;而且這種硬體結構的變化,能實時地適應計算任務要求的變化。可重構計算的底層技術是FPGA編程技術,可重構計算的優點是硬體設計的實現基於軟體的靈活性,並且保持了傳統的基於硬體方法的執行速度。其體系結構可變的特點,很好地適應了實際應用中的多元化需求。
  • MultiVAC白皮書:基於可信分片計算的高性能彈性公鏈
    當指令序列在足夠充裕的gas費用保證下順利完成,並且驗證通過之後,節點將通過共識將計算結果打包發布並獲得gas獎勵。為了更便捷的進行指令操作,MVM提供了面向BISC更友好的內存模型,該模型能夠將計算機物理資源進行隔離,並且為合約執行提供靈活的運行時支持,內置了棧空間和堆空間。
  • 英特爾發布全新一代內存和存儲產品
    通過使內存更靠近處理器,英特爾傲騰能夠滿足現代計算的需求。此外,英特爾還透露即將面向雲和企業級用戶發布代號為「Crow Pass」的第三代英特爾®傲騰™持久內存。隨著幾款全新傲騰產品的發布,我們不僅延續創新,進一步強化了我們的內存和存儲產品組合,還將持續賦能客戶更好地應對數位化轉型的複雜性。現階段,傲騰產品和技術正日益成為計算業務中的主流應用。而作為英特爾重要的組成部分,這些領先的內存和存儲產品將進一步推動包括AI、5G網絡、智能和自主邊緣計算等重點增長領域的長足發展。」
  • 英特爾、第四範式聯合研究成果入選國際頂會VLDB,傲騰持久內存加持...
    然而,伴隨著業務的持續擴張和數據量的指數級增長,實時內存資料庫所存在的潛在弊端與風險使其難以高效、低成本的滿足不斷增長的業務硬實時需求:· 高性能特徵存取對計算資源消耗巨大:為了保障線上服務的性能,特徵工程內存資料庫對內存的容量要求極高,企業通常需要配備20-30臺機器以滿足高性能計算需求所需的內存容量,總體擁有成本(TCO)居高不下。
  • 英特爾Rob Crooke:2019,拓展內存和存儲新疆界
    本文作者:Rob Crooke英特爾公司高級副總裁兼非易失性存儲解決方案事業部總經理在英特爾,我們不僅是在內存和存儲領域有所涉獵,而且專注於推動以數據為中心的轉型,並利用關鍵技術顛覆內存和存儲市場,彌合內存和存儲層級結構中成本和性能的差距。當前,我們正致力於打造一個智能互聯、以數據為中心的未來,而現在,這樣的未來已經到來。
  • 內存+關係型資料庫將成為重要趨勢
    仿佛一夜之間,內存技術就從高性能計算以及華爾街交易系統等小眾應用領域,轉變成為了目前主流的資料庫技術。 內存技術拋棄了傳統的磁碟驅動器,使用半導體存儲體讓資料庫性能得到極大的提升。SAP公司就是內存技術的忠實擁躉,他們全力推廣的HANA內存資料庫管理系統,號稱可以支持非常廣泛的應用場景。 內存技術已經無處不在,在分析設備,Hadoop集群以及NoSQL,NewSQL領域我們都能夠看到內存技術的身影,它已經成為一股不可忽視的力量。
  • 號稱捨棄馮諾依曼架構,突破內存牆瓶頸的AI晶片,面世了
    顯然,目前常見的解決AI晶片內存牆的方法都還未成功解決這一問題,其中很重要的原因在於,絕大部分的AI晶片,可以認為其為基於類CPU架構,專注於計算整合,通過提升並行度的方法進行龐大計算力的結構調整,對存儲資源的使用和調度,依然依賴於編譯器或傳統的緩存管理算法,無法解決內存牆問題。SFA架構如何突破內存牆瓶頸?
  • 高性能CPU搭配HyperX掠食者DDR4系列內存
    內存容量是基礎其他參數同樣重要    現代電子計算機都是基於馮諾依曼體系,計算與存儲分離,計算性能越強對存儲的要求也越高,新的i9-9900K或者R9-3900X的L1、L2、L3緩存容量及帶寬已經不是問題
  • Material Studio材料計算的工作站配置方案
    ,靈活方便的配置架構,使應用軟體在任何一臺支持基於Windows、Linux等主流作業系統的伺服器或工作站上最高效率的進行運算,從而最大限度的發揮工作站硬體性能和網絡資源。>   主要集中在對CPU和內存方面,MS軟體支持主流CPU的多核並行計算,在一個架構裡,頻率越高,核數,計算速度越快,內存方面主要體現在計算的規模上,隨著對自然世界的深入了解和分析,分析精度越來越高,計算量也越來越大,對內存的要求也在不斷遞增,
  • 高頻DDR4內存有沒有必要?實測數據給力
    ­  DDR4 內存降價是時候出手了­  前不久三星宣布量產 18nm DRAM 內存顆粒,隨著技術的不斷推進,內存顆粒價格不斷下調,內存價格不斷走低,即便還未全面普及的 DDR4 內存,標準的單條 8GB DDR4 2133 內存也已經全面跌入 200 元以內,基於此很多用戶用上了 16GB 內存,另一方面內存技術的進步
  • 使用非線性鐵電憶阻器執行低功率線性計算
    利用我們在新型內存開發方面的專業知識,我們的目標是基於憶阻器的內存計算,可以減輕傳統計算系統的某些效率約束。」憶阻器是用於增強計算機系統內存的非易失性電子組件。這些可編程電阻器可以整齊地包裝在小型但計算功能強大的交叉開關陣列中,該陣列可用於計算人工神經網絡的核心操作,充當存儲器並減少對外部數據的訪問,從而最終提高其能效。