精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

編譯優(yōu)化 | LLVM代碼生成技術(shù)詳解及在數(shù)據(jù)庫中的應(yīng)用

運維 數(shù)據(jù)庫運維
隨著IT基礎(chǔ)設(shè)施的發(fā)展,現(xiàn)代的數(shù)據(jù)處理系統(tǒng)需要處理更多的數(shù)據(jù)、支持更為復雜的算法。數(shù)據(jù)量的增長和算法的復雜化,為數(shù)據(jù)分析系統(tǒng)帶來了嚴峻的性能挑戰(zhàn)。

 [[407375]]

1. 前言

隨著IT基礎(chǔ)設(shè)施的發(fā)展,現(xiàn)代的數(shù)據(jù)處理系統(tǒng)需要處理更多的數(shù)據(jù)、支持更為復雜的算法。數(shù)據(jù)量的增長和算法的復雜化,為數(shù)據(jù)分析系統(tǒng)帶來了嚴峻的性能挑戰(zhàn)。近年來,我們可以在數(shù)據(jù)庫、大數(shù)據(jù)系統(tǒng)和AI平臺等領(lǐng)域看到很多性能優(yōu)化的技術(shù),技術(shù)涵蓋體系結(jié)構(gòu)、編譯技術(shù)和高性能計算等領(lǐng)域。作為編譯優(yōu)化技術(shù)的代表,本文主要介紹基于LLVM的代碼生成技術(shù)(簡稱Codeden)。

LLVM是一款非常流行的開源編譯器框架,支持多種語言和底層硬件。開發(fā)者可以基于LLVM搭建自己的編譯框架并進行二次開發(fā),將不同的語言或者邏輯編譯成運行在多種硬件上的可執(zhí)行文件。對于Codegen技術(shù)來說,我們主要關(guān)注LLVM IR的格式以及生成LLVM IR的API。在本文的如下部分,我們首先對LLVM IR進行介紹,然后介紹Codegen技術(shù)的原理和使用場景,最后我們介紹在阿里云自研的云原生數(shù)據(jù)倉庫產(chǎn)品AnalyticDB PostgreSQL中,Codegen的典型應(yīng)用場景。

2. LLVM IR簡介及上手教程

在編譯器理論與實踐中,IR是非常重要的一環(huán)。IR的全稱叫做Intermediate Representation,翻譯過來叫“中間表示”。 對于一個編譯器來說,從上層抽象的高級語言到底層的匯編語言,要經(jīng)歷很多個環(huán)節(jié)(pass),經(jīng)歷不同的表現(xiàn)形式。而編譯優(yōu)化技術(shù)有很多種,每種技術(shù)作用的編譯環(huán)節(jié)不同。但是IR是一個明顯的分水嶺。IR以上的編譯優(yōu)化,不需要關(guān)心底層硬件的細節(jié),比如硬件的指令集、寄存器文件大小等。IR以下的編譯優(yōu)化,需要和硬件打交道。LLVM最為著名是它的IR的設(shè)計。得益于巧妙地IR設(shè)計,LLVM向上可以支持不同的語言,向下可以支持不同的硬件,而且不同的語言可以復用IR層的優(yōu)化算法。

 

 

 

 

 

 

上圖展示了LLVM的一個框架圖。LLVM把整個編譯過程分為三步:(1)前端,把高級語言轉(zhuǎn)換為IR。(2)中端,在IR層做優(yōu)化。(3) 后端,把IR轉(zhuǎn)化為對應(yīng)的硬件平臺的匯編語言。因此LLVM的擴展性很好。比如你要實現(xiàn)一個名為toyc的語言、希望運行在ARM平臺上,你只需要實現(xiàn)一個toyc->LLVM IR的前端,其他部分調(diào)LLVM的模塊就可以了。或者你要搞一個新的硬件平臺,那么只需要搞定LLVM IR->新硬件這一階段,然后該硬件就可以支持很多種現(xiàn)存的語言。因此,IR是LLVM最有競爭力的地方,同時也是學習使用LLVM Codegen的最核心的地方。

2.1 LLVM IR基本知識

LLVM的IR格式非常像匯編,對于學習過匯編語言的同學來說,學會使用LLVM IR進行編程非常容易。對于沒學過匯編語言的同學,也不用擔心,匯編其實并不難。匯編難的不是學會,而是工程實現(xiàn)。因為匯編語言的開發(fā)難度,會隨著工程復雜度的提升呈指數(shù)級上升。接下來我們需要了解IR中最重要的三部分,指令格式、Basic Block & CFG,還有SSA。完整的LLVM IR信息請參考https:// llvm.org/docs/LangRef.h tml 。

指令格式 。LLVM IR提供了一種類似于匯編語言的三地址碼式的指令格式。下面的代碼片段是一個非常簡單的用LLVM IR實現(xiàn)的函數(shù),該函數(shù)的輸入是5個i32類型(int32)的整數(shù),函數(shù)的功能是計算這5個數(shù)的和并返回。LLVM IR是支持一些基本的數(shù)據(jù)類型的,比如i8、i32、浮點數(shù)等。LLVM IR中得變量的命名是以 "%"開頭,默認%0是函數(shù)的第一個參數(shù)、%1是第二個參數(shù),依次類推。機器生成的變量一般是以數(shù)字進行命名,如果是手寫的話,可以根據(jù)自己的喜好選擇合適的命名方法。LLVM IR的指令格式包括操作符、類型、輸入、返回值。例如 "%6 = add i32 %0, %1"的操作符號是"add"、類型是"i32"、輸入是"%0"和“%1”、返回值是"%6"。總的來說,IR支持一些基本的指令,然后編譯器通過這些基本指令的來完成一些復雜的運算。例如,我們在C中寫一個形如“A * B + C”的表達式在LLVM IR中是通過一條乘法和一條加法指令來完成的,另外可能也包括一些類型轉(zhuǎn)換指令。

  1. define i32 @ir_add(i32, i32, i32, i32, i32){ 
  2.   %6 = add i32 %0, %1 
  3.   %7 = add i32 %6, %2 
  4.   %8 = add i32 %7, %3 
  5.   %9 = add i32 %8, %4 
  6.   ret i32 %9 

Basic Block & CFG 。了解了IR的指令格式以后,接下來我們需要了解兩個概念:Basic Block(基本塊,簡稱BB)和Control Flow Graph(控制流圖,CFG)。下圖(左)展示了一個簡單的C語言函數(shù),下圖(中)是使用clang編譯出來的對應(yīng)的LLVM IR,下圖(右)是使用graphviz畫出來的CFG。結(jié)合這張圖,我們解釋下Basic Block和CFG的概念。

 

 

 

 

 

 

在我們平時接觸到的高級語言中,每種語言都會有很多分支跳轉(zhuǎn)語句,比如C語言中有for, while, if等關(guān)鍵字,這些關(guān)鍵字都代表著分支跳轉(zhuǎn)。開發(fā)者通過分支跳轉(zhuǎn)來實現(xiàn)不同的邏輯運算。匯編語言通常通過有條件跳轉(zhuǎn)和無條件跳轉(zhuǎn)兩種跳轉(zhuǎn)指令來實現(xiàn)邏輯運算,LLVM IR同理。比如在LLVM IR中"br label %7"意味著無論如何都跳轉(zhuǎn)到名為%7的label那里,這是一條無條件跳轉(zhuǎn)指令。"br i1 %10, label %11, label %22"是有條件跳轉(zhuǎn),意味著這如果%10是true則跳轉(zhuǎn)到名為%11的label,否則跳轉(zhuǎn)到名為%22的label。

在了解了跳轉(zhuǎn)指令這個概念后,我們介紹Basic Block的概念。一個Basic Block是指一段串行執(zhí)行的指令流,除了最后一句之外不會有跳轉(zhuǎn)指令,Basic Block入口的第一條指令叫做“Leading instruction”。除了第一個Basic Block之外,每個Basic Block都會有一個名字(label)。第一個Basic Block也可以有,只是有時候沒必要。例如在這段代碼當中一共有5個Basic Block。Basic Block的概念,解決了控制邏輯的問題。通過Basic Block, 我們可以把代碼劃分成不同的代碼塊,在編譯優(yōu)化中,有的優(yōu)化是針對單個Basic Block的,有些是針對多個Basic Block的。

CFG(Control Flow Graph, 控制流圖)其實就是由Basic Block以及Basic Block之間的跳轉(zhuǎn)關(guān)系組成的一個圖。例如上圖所示的代碼,一共有5個Basic Block,箭頭列出了Basic Block之間的跳轉(zhuǎn)關(guān)系,共同組成了一個CFG。如果一個Basic Block只有一個箭頭指向別的Block,那么這個跳轉(zhuǎn)就是無條件跳轉(zhuǎn),否則是有條件跳轉(zhuǎn)。CFG是編譯理論中一個比較簡單而且很基礎(chǔ)的概念,CFG更進一步是DFG(Data Flow Graph,數(shù)據(jù)流圖),很多進階的編譯優(yōu)化算法都是基于DFG的。對于使用LLVM進行Codegen開發(fā)的同學,理解CFG的概念即可。

SSA 。SSA的全稱是Static Single Assignment(靜態(tài)單賦值),這是編譯技術(shù)中非常基礎(chǔ)的一個理念。SSA是學習LLVM IR必須熟悉的概念,同時也是最難理解的一個概念。細心的讀者在觀察上面列出的IR代碼時會發(fā)現(xiàn),每個“變量”只會被賦值一次,這就是SSA的核心思想。因為從編譯器的角度來看,編譯器不關(guān)心“變量”,編譯器是以“數(shù)據(jù)”為中心進行設(shè)計的。每個“變量”的每次寫入,都生成了一個新的數(shù)據(jù)版本,編譯器的優(yōu)化是圍繞數(shù)據(jù)版本展開的。接下來我們用如下的C語言代碼來解釋這一思想。

 

 

 

 

 

 

上圖(左)展示了一段簡單的C代碼,上圖(右)是這段代碼的SSA版本,也就是“編譯器眼中的代碼”。在C語言中,我們知道數(shù)據(jù)都是用變量來存儲的,因此數(shù)據(jù)操作的核心是變量,開發(fā)者需要關(guān)心變量的生存時間、何時被賦值、何時被使用。但是編譯器只關(guān)心數(shù)據(jù)的流向,因此每次賦值操作都會生成一個新的左值。例如左邊代碼只有一個a, 但是在右邊的代碼有4個變量,因為a里面的數(shù)據(jù)一共有4個版本。除了每次賦值操作會生成一個新的變量,最后的一個phi節(jié)點會生成一個新的變量。在SSA中,每個變量都代表數(shù)據(jù)的一個版本。也就是說,高級語言以變量為核心,而SSA格式以數(shù)據(jù)為核心。SSA中每次賦值操作都會生成一個版本的數(shù)據(jù),因此在寫IR的時候,時刻牢記IR的變量和高層語言不同,一個IR的變量代表數(shù)據(jù)的一個版本。Phi節(jié)點是SSA中的一個重要概念。在這個例子當中,a_4的取值取決于之前執(zhí)行了哪個分支,如果執(zhí)行了第一個分支,那么a_4 = a_1, 依次類推。Phi節(jié)點通過判斷這段代碼是從哪個Basic Block跳轉(zhuǎn)而來,選擇合適的數(shù)據(jù)版本。LLVM IR自然也是需要開發(fā)者寫Phi節(jié)點的,在循環(huán)、條件分支跳轉(zhuǎn)的地方,往往需要手寫很多phi節(jié)點,這是寫LLVM IR時邏輯上比較難處理的地方。

2.2 學會使用LLVM IR寫程序

熟悉LLVM IR最好的辦法就是使用IR寫幾個程序。在開始寫之前,建議先花30分鐘-1個小時再粗略閱讀下官方手冊(

https:// llvm.org/docs/LangRef.h tml ),熟悉下都有哪些指令的類型。接下來我們通過兩個簡單的case熟悉下LLVM IR編程的全部流程。

下面是一個循環(huán)加法的函數(shù)片段。這個函數(shù)一共包含三個Basic Block,loop、loop_body和final。其中l(wèi)oop是整個函數(shù)的開始,loop_body是函數(shù)的循環(huán)體,final是函數(shù)的結(jié)尾。在第5行和第6行,我們使用phi節(jié)點來實現(xiàn)結(jié)果和循環(huán)變量。

  1. define i32 @ir_loopadd_phi(i32*, i32){ 
  2.   br label %loop 
  3.        
  4. loop: 
  5.   %i = phi i32 [0,%2], [%newi,%loop_body] 
  6.   %res = phi i32[0,%2], [%new_res, %loop_body] 
  7.   %break_flag = icmp sge i32 %i, %1 
  8.   br i1 %break_flag, label %final, label %loop_body  
  9.        
  10. loop_body: 
  11.   %addr = getelementptr inbounds i32, i32* %0, i32 %i 
  12.   %val = load i32, i32* %addr, align 4 
  13.   %new_res = add i32 %res, %val 
  14.   %newi = add i32 %i, 1 
  15.   br label %loop 
  16.  
  17. final
  18.   ret i32 %res; 

下面是一個數(shù)組冒泡排序的函數(shù)片段。這個函數(shù)包含兩個循環(huán)體。LLVM IR實現(xiàn)循環(huán)本身就比較復雜,兩個循環(huán)嵌套會更加復雜。如果能夠用LLVM IR實現(xiàn)一個冒泡算法,基本上就理解了LLVM的整個邏輯了。

  1. define void @ir_bubble(i32*, i32) { 
  2.   %r_flag_addr = alloca i32, align 4 
  3.   %j = alloca i32, align 4 
  4.   %r_flag_ini = add i32 %1, -1 
  5.   store i32 %r_flag_ini, i32* %r_flag_addr, align 4 
  6.   br label %out_loop_head 
  7. out_loop_head: 
  8.   ;check break 
  9.   store i32 0, i32* %j, align 4 
  10.   %tmp_r_flag = load i32, i32* %r_flag_addr, align 4 
  11.   %out_break_flag = icmp sle i32 %tmp_r_flag, 0 
  12.   br i1 %out_break_flag, label %final, label %in_loop_head 
  13.   in_loop_head: 
  14.     ;check break 
  15.     %tmpj_1 = load i32, i32* %j, align 4 
  16.     %in_break_flag = icmp sge i32 %tmpj_1, %tmp_r_flag 
  17.     br i1 %in_break_flag, label %out_loop_tail, label %in_loop_body 
  18.   in_loop_body: 
  19.     ;read & swap 
  20.     %tmpj_left = load i32, i32* %j, align 4 
  21.     %tmpj_right = add i32 %tmpj_left, 1 
  22.     %left_addr = getelementptr inbounds i32, i32* %0, i32 %tmpj_left 
  23.     %right_addr = getelementptr inbounds i32, i32* %0, i32 %tmpj_right 
  24.     %left_val = load i32, i32* %left_addr, align 4 
  25.     %right_val = load i32, i32* %right_addr, align 4 
  26.     ;swap check 
  27.     %swap_flag = icmp sge i32 %left_val, %right_val 
  28.     %left_res  = select i1 %swap_flag, i32 %right_val, i32 %left_val  
  29.     %right_res = select i1 %swap_flag, i32 %left_val, i32 %right_val 
  30.     store i32 %left_res, i32* %left_addr, align 4 
  31.     store i32 %right_res, i32* %right_addr, align 4 
  32.     br label %in_loop_end 
  33.   in_loop_end: 
  34.     ;update j 
  35.     %tmpj_2 = load i32, i32* %j, align 4 
  36.     %newj = add i32 %tmpj_2, 1 
  37.     store i32 %newj, i32* %j, align 4 
  38.     br label %in_loop_head 
  39. out_loop_tail: 
  40.   ;update r_flag  
  41.   %tmp_r_flag_1 = load i32, i32* %r_flag_addr, align 4 
  42.   %new_r_flag = sub i32 %tmp_r_flag_1, 1 
  43.   store i32 %new_r_flag, i32* %r_flag_addr, align 4 
  44.   br label %out_loop_head 
  45. final
  46.   ret void 

我們把如上的LLVM IR用clang編譯器編譯成object文件,然后和C語言寫的程序鏈接到一起,即可正常調(diào)用。在上面提到的case中,我們只使用了i32、i64等基本數(shù)據(jù)類型,LLVM IR中支持struct等高級數(shù)據(jù)類型,可以實現(xiàn)更為復雜的功能。

2.3 使用LLVM API實現(xiàn)Codegen

編譯器本質(zhì)上就是調(diào)用各種各樣的API,根據(jù)輸入去生成對應(yīng)的代碼,LLVM Codegen也不例外。在LLVM內(nèi)部,一個函數(shù)是一個class,一個Basic Block試一個class, 一條指令、一個變量都是一個class。用LLVM API實現(xiàn)codegen就是根據(jù)需求,用LLVM內(nèi)部的數(shù)據(jù)結(jié)構(gòu)去實現(xiàn)相應(yīng)的IR。

  1. Value *constant = Builder.getInt32(16); 
  2.     Value *Arg1 = fooFunc->arg_begin(); 
  3.     Value *val = createArith(Builder, Arg1, constant); 
  4.  
  5.     Value *val2 = Builder.getInt32(100); 
  6.     Value *Compare = Builder.CreateICmpULT(val, val2, "cmptmp"); 
  7.     Value *Condition = Builder.CreateICmpNE(Compare, Builder.getInt1(0), "ifcond"); 
  8.  
  9.     ValList VL; 
  10.     VL.push_back(Condition); 
  11.     VL.push_back(Arg1); 
  12.  
  13.     BasicBlock *ThenBB = createBB(fooFunc, "then"); 
  14.     BasicBlock *ElseBB = createBB(fooFunc, "else"); 
  15.     BasicBlock *MergeBB = createBB(fooFunc, "ifcont"); 
  16.     BBList List; 
  17.     List.push_back(ThenBB); 
  18.     List.push_back(ElseBB); 
  19.     List.push_back(MergeBB); 
  20.  
  21.     Value *v = createIfElse(Builder, List, VL); 

如上是一個用LLVM API實現(xiàn)codegen的例子。其實這就是個用C++寫IR的過程,如果知道如何寫IR的話,只需要熟悉下這套API就可以了。這套API提供了一些基本的數(shù)據(jù)結(jié)構(gòu),比如指令、函數(shù)、基本塊、llvm builder等,然后我們只需要調(diào)用相應(yīng)的函數(shù)去生成這些對象即可。一般來說,首先我們先生成函數(shù)的原型,包括函數(shù)名字、參數(shù)列表、返回類型等。然后我們在根據(jù)函數(shù)的功能,確定都需要有哪些Basic Block以及Basic Block之間的跳轉(zhuǎn)關(guān)系,然后生成相應(yīng)的Basic。最后我們再按照一定的順序去給每個Basic Block填充指令。邏輯是,這個流程和用LLVM IR寫代碼是相仿的。

3. Codegen技術(shù)分析

如果我們用上文所描述的方法,生成一些簡單的函數(shù),并且用C寫出對應(yīng)的版本進行性能對比,我們就會發(fā)現(xiàn),LLVM IR的性能并不會比C快。一方面,計算機底層執(zhí)行的是匯編,C語言本身和匯編是非常接近的,了解底層的程序員往往能夠從C代碼中推測出大概會生成什么樣的匯編。另一方面,現(xiàn)代編譯器往往做了很多優(yōu)化,一些大大減輕了程序員的優(yōu)化負擔。因此,使用LLVM IR進行Codegen并不會獲得比手寫C更好的性能,而且使用LLVM Codegen有一些明顯的缺點。想要真正用好LLVM,我們還需要熟悉LLVM的特點。

3.1 缺點分析

缺點1:開發(fā)難。 實際開發(fā)中幾乎不會有工程使用匯編作為主要開發(fā)語言,因為開發(fā)難度太大了,有興趣的小伙伴可以試著寫個快排感受一下。即使是數(shù)據(jù)庫、操作系統(tǒng)這樣的基礎(chǔ)軟件,往往也只是在少數(shù)的地方會用到匯編。使用LLVM IR開發(fā)會有類似的問題。比如上文展示的最復雜例子是冒泡算法。開發(fā)者用C寫個冒泡只需要幾分鐘,但是用LLVM IR寫個冒泡可能要一個小時。另外,LLVM IR很難處理復雜的數(shù)據(jù)結(jié)構(gòu),比如結(jié)構(gòu)體、類。除了LLVM IR中的那些基本數(shù)據(jù)結(jié)構(gòu)外,新增一個復雜的數(shù)據(jù)結(jié)構(gòu)非常難。因此在實際的開發(fā)當中,采用Codegen會導致開發(fā)難度指數(shù)級上升。

缺點2:調(diào)試難 。開發(fā)者通常通過單步跟蹤的方式去調(diào)試代碼,但是LLVM IR是不支持的。一旦代碼出問題,只能是人肉一遍一遍看LLVM IR。如果懂匯編的話,可以通過單步跟蹤生成的匯編進行調(diào)試,但是匯編語言和IR之間并不是簡單的映射關(guān)系,因此只能一定程度上降低調(diào)試難度,并不完全解決調(diào)試的問題。

缺點3: 運行成本 。生成LLVM IR往往很快,但是生成的IR需要調(diào)用LLVM 中的工具進行優(yōu)化、以及編譯成二進制文件,這個過程是需要時間的(請聯(lián)想一下GCC編譯的速度)。在數(shù)據(jù)庫的開發(fā)過程中,我們的經(jīng)驗值是每個函數(shù)大約需要10ms-100ms的codegen成本。大部分的時間花在了優(yōu)化IR和IR到匯編這兩步。

3.2 適用場景

了解了LLVM Codegen的缺點,我們才能去分析其優(yōu)點、選擇合適場景。下面這部分是團隊在開發(fā)過程中總結(jié)的適合使用LLVM Codegen的場景。

場景1:Java/python等語言 。上文中提到過LLVM IR并不會比C快,但是會比Java/python等語言快啊。例如在Java中,有時候為了提升性能,會通過JNI調(diào)用一些C的函數(shù)提升性能。同理,Java也可以調(diào)用LLVM IR生成的函數(shù)提升性能。

場景2:硬件和語言不兼容 。LLVM支持多種后端,比如X86、ARM和GPU。對于一些硬件與語言不兼容的場景,可以利用LLVM實現(xiàn)兼容。例如如果我們的系統(tǒng)是用Java語言開發(fā)、想要調(diào)用GPU,可以考慮用LLVM IR生成GPU代碼,然后通過JNI的方法進行調(diào)用。這套方案不僅支持NVIDIA的GPU,也支持AMD的GPU,而且對應(yīng)生成的IR也可以在CPU上執(zhí)行。

場景3:邏輯簡化 。以數(shù)據(jù)庫為例,數(shù)據(jù)庫執(zhí)行引擎在執(zhí)行過程中需要做大量的數(shù)據(jù)類型、算法邏輯相關(guān)的判斷。這主要是由于SQL中的數(shù)據(jù)類型和邏輯,很多是在數(shù)據(jù)庫開發(fā)時無法確定的,只能在運行時決定。這一部分過程,也被稱為“解釋執(zhí)行”。我們可以利用LLVM在運行時生成代碼,由于這個時候數(shù)據(jù)類型和邏輯已經(jīng)確定,我們可以在LLVM IR中刪除那些不必要的判斷操作,從而實現(xiàn)性能的提升。

4. LLVM在數(shù)據(jù)庫中的應(yīng)用

在數(shù)據(jù)庫當中,團隊是用LLVM來進行表達式的處理,接下來我們以PostgreSQL數(shù)據(jù)庫和云原生數(shù)據(jù)倉庫AnalyticDB PostgreSQL為對比,解釋LLVM的應(yīng)用方法。

PostgreSQL為了實現(xiàn)表達式的解釋執(zhí)行,采用了一套“拼函數(shù)”的方案。PostgreSQL中實現(xiàn)了大量C函數(shù),比如加減法、大小比較等,不同類型的都有。SQL在生成執(zhí)行計劃階段會根據(jù)表達式符號的類型和數(shù)據(jù)類型選擇相應(yīng)的函數(shù)、把指針存下來,等執(zhí)行的時候再調(diào)用。因此對于 "a > 10 and b < 5"這樣的過濾條件,假設(shè)a和b都是int32,PostgreSQL實際上調(diào)用了“Int8AndOp(Int32GT(a, 10), Int32LT(b, 5))”這樣一個函數(shù)組合,就像搭積木一樣。這樣的方案有兩個明顯的性能問題。一方面這種方案會帶來比較多次數(shù)的函數(shù)調(diào)用,函數(shù)調(diào)用本身是有成本的。另一方面,這種方案必須要實現(xiàn)一個統(tǒng)一的函數(shù)接口,函數(shù)內(nèi)部和外部都需要做一些類型轉(zhuǎn)換,這也是額外的性能開銷。Odyssey使用LLVM 進行codegen,可以實現(xiàn)最小化的代碼。因為在SQL下發(fā)以后,數(shù)據(jù)庫是知道表達式的符號和輸入數(shù)據(jù)的類型的,因此只需要根據(jù)需求選取相應(yīng)的IR指令就可以了。因此只需要三條IR指令,就可以實現(xiàn)這個表達式,然后我們把表達式封裝成一個函數(shù),就可以在執(zhí)行的時候調(diào)用了。這次操作,把多次函數(shù)調(diào)用簡化成了一次函數(shù)調(diào)用,大大減少了指令的總數(shù)量。

  1. // 樣例SQL 
  2. select count(*) from table where a > 10 and b < 5
  3.  
  4. // PostgreSQL解釋執(zhí)行方案:多次函數(shù)調(diào)用 
  5. result = Int8AndOp(Int32GT(a, 10), Int32LT(b, 5)); 
  6.  
  7. // AnalyticDB PostgreSQL方案:使用LLVM codegen生成最小化底層代碼 
  8. %res1 = icmp ugt i32 %a, 10
  9. %res2 = icmp ult i32 %b, 5;  
  10. %res = and i8 %res1, %res2; 

在數(shù)據(jù)庫中,表達式主要出現(xiàn)在幾個場景。一類是過濾條件,通常出現(xiàn)在where條件中。一類是輸出列表,一般跟在select之后。有些算子,比如join、agg等,它的判斷條件中也可能會出現(xiàn)一些比較復雜的表達式。因此表達式的處理是會出現(xiàn)在數(shù)據(jù)庫執(zhí)行引擎的各個模塊的。在AnalyticDB PostgreSQL版中,開發(fā)團隊抽象出了一個表達式處理框架,通過LLVM Codegen來處理這些表達式,從而提高了執(zhí)行引擎的整體性能。

 

 

 

 

 

 

5. 總結(jié)

LLVM作為一個流行的開源編譯框架,近年來被用于數(shù)據(jù)庫、AI等系統(tǒng)的性能加速。由于編譯器理論本身門檻較高,因此LLVM的學習有一定的難度。而且從工程上,還需要對LLVM的工程特點和性能特征有比較準確的理解,才能找到合適的加速場景。阿里云數(shù)據(jù)庫團隊的云原生數(shù)據(jù)倉庫產(chǎn)品AnalyticDB PostgreSQL版基于LLVM實現(xiàn)了一套運行時的表達式處理框架,能夠有效地提高系統(tǒng)在進行復雜數(shù)據(jù)分析時地性能。

 

責任編輯:張燕妮 來源: 知乎
相關(guān)推薦

2021-06-28 09:26:51

數(shù)據(jù)庫LLVM

2009-10-27 16:36:07

Oracle如何解鎖

2024-11-13 15:15:46

2009-07-22 11:45:43

2023-03-03 08:00:00

重采樣數(shù)據(jù)集

2011-05-19 10:29:40

數(shù)據(jù)庫查詢

2011-04-12 13:44:17

CachéOracle數(shù)據(jù)庫

2014-06-10 15:07:19

Oracle數(shù)據(jù)庫優(yōu)化

2018-05-17 23:07:12

2011-03-04 10:03:45

EJB數(shù)據(jù)庫應(yīng)用

2010-10-09 10:29:29

MySQL外鍵

2011-04-02 14:50:58

數(shù)據(jù)庫代碼

2011-05-18 09:39:19

Oracle數(shù)據(jù)庫性能優(yōu)化

2009-03-19 08:56:58

pureXMLDB2數(shù)據(jù)結(jié)構(gòu)

2011-05-17 15:02:15

ORACLE數(shù)據(jù)庫備份

2023-03-07 16:21:26

2010-04-09 16:51:24

Oracle數(shù)據(jù)庫

2011-08-17 17:29:32

Windows編譯MySQL

2024-02-04 09:41:51

人工智能

2010-04-07 14:22:46

點贊
收藏

51CTO技術(shù)棧公眾號

亚洲在线电影| 2020最新国产精品| 大美女一区二区三区| 欧美精品video| 国产一级伦理片| 欧美成人影院| 亚洲欧洲精品一区二区精品久久久| 国产日本欧美一区| 国产精品三区在线观看| 亚洲图色一区二区三区| 亚洲va韩国va欧美va精品 | vam成人资源在线观看| 亚洲婷婷综合久久一本伊一区| 97超碰人人模人人爽人人看| 日韩美女黄色片| 成人午夜国产| 欧美伦理视频网站| 丁香婷婷综合激情| 深夜福利免费在线观看| 蜜桃在线一区二区三区| 久久久免费电影| 四虎国产精品成人免费入口| 成人污版视频| 欧美性猛交xxxx富婆弯腰| 亚洲成人蜜桃| 好吊视频一二三区| 青草av.久久免费一区| 日韩一中文字幕| av2014天堂网| 国产欧美88| 色婷婷一区二区| 艳母动漫在线观看| 青春有你2免费观看完整版在线播放高清| 奇米综合一区二区三区精品视频| 日韩中文字幕在线| 30一40一50老女人毛片| 亚洲精品v亚洲精品v日韩精品| 日本高清无吗v一区| 免费极品av一视觉盛宴| 熟妇人妻一区二区三区四区| 久久99日本精品| 亲爱的老师9免费观看全集电视剧| 91高清免费看| 精品一级毛片| 日韩大陆欧美高清视频区| 99999精品| a一区二区三区| 香港成人在线视频| 国产91视频一区| 黄色在线免费看| 国产日韩精品一区二区三区 | www.久久久.com| 色婷婷综合久久久久中文 | 中文字幕在线1| 91久久精品无嫩草影院| 欧美一区二区三区小说| 爱情岛论坛亚洲首页入口章节| 婷婷色在线播放| 国产精品灌醉下药二区| 神马一区二区影院| 暖暖视频在线免费观看| 波多野结衣亚洲一区| 91精品久久香蕉国产线看观看| 97国产精品久久久| 狠狠色综合日日| 日本在线观看天堂男亚洲| 日韩 欧美 中文| 在线亚洲一区| 久久人人97超碰精品888| 九九热精品在线观看| 自拍偷拍欧美| 爱福利视频一区| 极品尤物一区二区| 欧美gayvideo| 亚洲视频在线视频| 无码人妻精品一区二区中文| 亚洲另类春色校园小说| 日韩成人高清在线| 朝桐光av一区二区三区| 亚洲国产最新| 亚洲色图13p| 青青草华人在线视频| 午夜国产一区二区| 欧美xxxx综合视频| 精品无码黑人又粗又大又长| 亚洲国产一区二区三区高清| 97精品一区二区视频在线观看| 日韩精品一区二区不卡| 久久综合中文| 国产欧美日韩免费| 做爰视频毛片视频| 狠狠狠色丁香婷婷综合激情| 亚洲在线视频福利| 国产绿帽一区二区三区| 国产精品亚洲а∨天堂免在线| 成人动漫视频在线观看完整版| 亚洲女同志亚洲女同女播放| av激情亚洲男人天堂| 欧美日本韩国在线| 成人高清免费在线播放| 亚洲色大成网站www久久九九| 成人av在线播放观看| 天堂√8在线中文| 欧美亚洲一区二区三区四区| 美女网站色免费| 亚洲一二三区视频| 亚洲欧美国产日韩中文字幕| 日本一卡二卡在线播放| 欧美激情四色| 日本高清+成人网在线观看| 一区二区乱子伦在线播放| 国产一区二区免费在线| 精品一区二区三区日本| 永久免费在线观看视频| 亚洲精品免费在线| 妞干网在线观看视频| 成人免费直播| 日韩欧美一二三四区| 欧美成人国产精品一区二区| 欧美福利电影在线观看| 日本亚洲欧洲色| 精品人妻伦一区二区三区久久| 久久免费视频一区| 婷婷精品国产一区二区三区日韩| 女人黄色免费在线观看| 欧美熟乱第一页| 国产精品一区二区人妻喷水| 欧美mv日韩| 欧美在线视频一二三| 国产高清视频免费观看| 国产三级精品三级在线专区| 国产毛片视频网站| 高清一区二区| 亚洲精品乱码久久久久久按摩观| 91大神福利视频| 久久久久国产精品午夜一区| 国产精品18毛片一区二区| 久操免费在线| 欧美午夜丰满在线18影院| gogo亚洲国模私拍人体| 国产成人调教视频在线观看 | 国产精品区一区| 理论片午午伦夜理片在线播放| 欧美性少妇18aaaa视频| 蜜臀视频在线观看| 欧美熟乱15p| 日本免费一区二区三区视频观看| 精品乱子伦一区二区| 中文字幕在线一区| 特级丰满少妇一级| 精品av一区二区| 日本一区二区不卡| 亚洲区小说区图片区| 亚洲mv在线观看| 四虎永久免费观看| 欧美精品一卡| 亚洲自拍偷拍区| 国产在线观看a| 欧美群妇大交群的观看方式| 精品少妇一区二区三区免费观| 亚洲成人直播| 成人动漫视频在线观看免费| 欧洲成人综合网| 日韩欧美在线不卡| 99热精品免费| 国产不卡一区视频| 成人免费观看在线| 国产精品xxxav免费视频| 欧美另类xxx| 懂色av一区二区三区四区| 亚洲一区二区欧美激情| 国产黑丝一区二区| 国产精品人人爽人人做我的可爱| 国产欧美一区二区视频| av色综合久久天堂av色综合在| 91精品国产综合久久福利软件 | 国产精品久久久久久69| 最新高清无码专区| www.偷拍.com| 亚洲茄子视频| 日韩av一区二区三区美女毛片| 欧美日韩在线精品一区二区三区激情综合 | 少妇人妻偷人精品一区二区| 色哟哟在线观看一区二区三区| 一二三四国产精品| 国产精品亚洲一区二区三区妖精| 日韩中文字幕三区| 欧美oldwomenvideos| 国产精品麻豆免费版| 色天使综合视频| 欧美大奶子在线| 三级国产在线观看| 欧美电影在线免费观看| 国产一级在线免费观看| 欧美国产精品劲爆| 美女伦理水蜜桃4| 久久精品国产精品青草| 国内精品在线观看视频| 色狮一区二区三区四区视频| 国产麻豆乱码精品一区二区三区| 成人国产网站| 2019最新中文字幕| 大地资源网3页在线观看| 国产视频精品久久久| av在线亚洲天堂| 在线精品视频免费观看| 国产性xxxx高清| 亚洲四区在线观看| a天堂中文字幕| 99麻豆久久久国产精品免费优播| 欧美在线aaa| 免费日韩av片| 给我免费播放片在线观看| 天天综合网91| 水蜜桃一区二区三区| 日本高清精品| 国产91在线播放| mm视频在线视频| 欧美成人小视频| 91看片在线观看| 日韩精品免费视频| 丰满人妻一区二区| 91精品国产综合久久久久久久| 一级黄色av片| 五月婷婷久久综合| 久热精品在线观看| 亚洲欧洲综合另类| 欧美一区二区三区观看| 国产拍欧美日韩视频二区| 少妇饥渴放荡91麻豆| 国产mv日韩mv欧美| 免费人成视频在线播放| 久久国产视频网| www.日本xxxx| 久久亚洲精品伦理| 日韩中文字幕三区| 国产毛片一区| 欧美一级在线看| 国产精品日韩精品欧美精品| 99久久国产综合精品五月天喷水| 欧美先锋影音| 久久综合久久久久| 国产综合网站| 精品无码国产一区二区三区av| 中文字幕免费精品| 视色,视色影院,视色影库,视色网| 国产精品成人一区二区不卡| 青春草在线视频免费观看| 91视频综合| 手机福利在线视频| 久久久久久久久久久9不雅视频 | 激情综合视频| 国产精品久久久久久久乖乖| 影音先锋久久精品| 国产黄视频在线| 久久性色av| 最近中文字幕一区二区| 久久se精品一区精品二区| 亚洲18在线看污www麻豆| 国内精品伊人久久久久av影院 | 好男人www社区| 久久激情五月婷婷| 日韩欧美中文在线视频| 国产福利一区二区三区视频| 国产一级免费片| 91麻豆文化传媒在线观看| 成人性生交大免费看| 国产偷v国产偷v亚洲高清 | 欧美日韩国产在线看| 国产又大又黄又粗| 欧美性大战久久久| aaa一区二区| 国产丝袜一区二区三区免费视频| 黄色大片在线免费观看| 精品国产欧美成人夜夜嗨| 亚洲91av| 日本最新高清不卡中文字幕| 色综合视频一区二区三区日韩| 亚洲精品欧美日韩| 亚洲福利天堂| 天堂av免费看| 国产精品综合| 手机av在线网| 99久久免费视频.com| 能直接看的av| 亚洲图片自拍偷拍| 国产成人无码av| 欧美一区日本一区韩国一区| 无码精品人妻一区二区三区影院| 伊人成人开心激情综合网| 在线视频中文字幕第一页| 日本精品一区二区三区在线| 24小时成人在线视频| 国产在线精品一区二区三区| 成人精品中文字幕| 青青青青草视频| 久久99这里只有精品| 超碰97在线资源站| 亚洲免费av在线| 男人天堂av在线播放| 日韩手机在线导航| 成年人视频在线观看免费| 韩国欧美亚洲国产| 91麻豆精品国产综合久久久| 久久久福利视频| 欧美黄污视频| 污版视频在线观看| 97久久超碰国产精品| 99精品久久久久| 欧美性做爰猛烈叫床潮| 日韩在线观看视频网站| 久久精品电影一区二区| 欧美成人ⅴideosxxxxx| 国产精品久久久久久久小唯西川 | 精品国偷自产在线视频99| 国产美女精品写真福利视频| 91久久中文字幕| 日韩大片在线播放| 37pao成人国产永久免费视频| 国产精品1区2区| 国产精品18在线| 色哦色哦哦色天天综合| 天堂中文字幕av| 久久久久国产一区二区三区| 91视频亚洲| 一区二区三区四区欧美| 日本午夜精品视频在线观看 | 亚洲一区二区三区四区五区中文| 亚洲熟妇av乱码在线观看| 一区二区三区美女xx视频| 都市激情综合| 鲁丝片一区二区三区| 国产精品久久777777毛茸茸| 亚洲视频 中文字幕| 亚洲精品欧美综合四区| 国产绿帽一区二区三区| 日韩视频在线一区| 国产一区二区三区四区五区3d| 欧洲国产精品| 日韩在线一二三区| 欧美色图亚洲激情| 欧美性xxxxxxx| 户外极限露出调教在线视频| 国产91精品视频在线观看| 欧洲亚洲视频| 久久精品午夜福利| 久久精品免费在线观看| 无码人妻熟妇av又粗又大| 亚洲欧洲一区二区三区久久| 忘忧草在线影院两性视频| 蜜桃麻豆91| 丝袜国产日韩另类美女| 韩国三级hd中文字幕| 欧美在线一区二区| 日本中文字幕在线观看| 91久久精品美女高潮| 国产精品二区影院| 亚洲精品女人久久久| 色婷婷亚洲综合| av电影在线网| 92国产精品久久久久首页| 亚洲小说欧美另类社区| 国产麻豆天美果冻无码视频| 色悠久久久久综合欧美99| 91网页在线观看| 97久久天天综合色天天综合色hd | 伊人开心综合网| 手机看片一区二区三区| 国产成人精品a视频一区www| 日韩国产一区二区| 操人视频免费看| 亚洲超丰满肉感bbw| 国产女主播在线直播| 成人精品视频在线| 极品中文字幕一区| 在线小视频你懂的| 91精品国产麻豆| 在线女人免费视频| 一区二区国产日产| 不卡电影一区二区三区| 亚洲 欧美 中文字幕| 久久亚洲精品中文字幕冲田杏梨| 97se亚洲| 天天操天天摸天天爽| 亚洲精品免费看| 狠狠色伊人亚洲综合网站l| 亚洲直播在线一区| 天堂成人免费av电影一区| 国产一二三区精品| 亚洲美女av电影| 高清一区二区三区av| 日本福利视频在线| 亚洲免费av在线| 国产精品免费观看| 国产精品露出视频| 久久精品国产一区二区| 国产精品美女久久久久av爽| 久久精品精品电影网| 综合亚洲自拍| 潘金莲一级淫片aaaaa|