活动回顾|Apache Doris 向量化技术实现与后续规划
引言
Doris 向量化設(shè)計(jì)與實(shí)現(xiàn)
01????什么是向量化
向量化是指計(jì)算從一次對(duì)一個(gè)值進(jìn)行運(yùn)算轉(zhuǎn)換為一次對(duì)一組值進(jìn)行運(yùn)算的過程, 從不同的角度來分析,我將拆分成兩個(gè)方面來探討或思考這個(gè)問題。 從CPU的角度 現(xiàn)代 CPU 支持將單個(gè)指令應(yīng)用于多個(gè)數(shù)據(jù)(SIMD)的向量運(yùn)算。例如,具有 128 位寄存器的 CP U可以保存 4 個(gè) 32 位數(shù)并進(jìn)行一次計(jì)算,比一次執(zhí)行一條指令快 4 倍。
比如我們?cè)趦?nèi)存當(dāng)中有 4 個(gè) 32 位的 int ,進(jìn)行計(jì)算時(shí)傳統(tǒng)的 CPU 沒有 SIMD,或者說沒有向量化支持的 CPU 要進(jìn)行四次從內(nèi)存中 Load 數(shù)據(jù),再進(jìn)行 4 次乘法計(jì)算,然后把結(jié)果寫回到內(nèi)存當(dāng)中同樣要進(jìn)行 4 次。假如我們能夠支持 SIMD ,我們可以一次載入多個(gè)連續(xù)的內(nèi)存數(shù)據(jù),這樣我們就只有一次數(shù)據(jù)的 Load ,一次的計(jì)算,然后得到 4 個(gè)結(jié)果寫到 4 個(gè)寄存器里面,然后這 4 個(gè)寄存器再寫回到內(nèi)存當(dāng)中,就完成了一次向量化的指令計(jì)算操作。這樣的操作能夠比傳統(tǒng)的CPU快 4 倍。 隨著 CPU 的發(fā)展,現(xiàn)在大家常用的都是 128 位的 SSE 的指令,后面又多了 256 位的 AVX 指令,以及英特爾現(xiàn)在最新的 AVX512 的指令。隨著寄存器的位數(shù)不斷變長(zhǎng),我們一次向量化運(yùn)算的一組值可以變得越來越多,它的效率會(huì)越來越高。但這不一定是線性的關(guān)系,不一定隨著寄存機(jī)的位數(shù)呈線性的性能增長(zhǎng),但是能夠保證一次對(duì)一組值的操作是更多更快的。 這是在CPU角度,我們?nèi)タ聪蛄炕@個(gè)問題。
從數(shù)據(jù)庫(kù)的角度
從數(shù)據(jù)庫(kù)角度也是計(jì)算從一次對(duì)一個(gè)值進(jìn)行運(yùn)算轉(zhuǎn)換為一次對(duì)一組值進(jìn)行運(yùn)算的過程。-
數(shù)據(jù)庫(kù)執(zhí)行引擎:
1. 將 Next Tuple ,變成 Next Batch 。
2. 內(nèi)存中 Batch 的數(shù)據(jù)不是以行的形式存在,而是以列的形式存在,算子都是在列上進(jìn)行運(yùn)算。
在數(shù)據(jù)庫(kù)執(zhí)行引擎的角度與 CPU 的角度也是類似,傳統(tǒng)的數(shù)據(jù)庫(kù)執(zhí)行引擎都是一行一行處理數(shù)據(jù)的。我們可以看下面這個(gè)圖。
所以內(nèi)存當(dāng)中的數(shù)據(jù)不再以行的形式來存在,而是以列的形式存在,所有的計(jì)算都通過列的方式進(jìn)行連續(xù)的計(jì)算。我們可以看右邊這張圖,比如我們有一個(gè)數(shù)據(jù)掃描的操作,原本按照左邊這張圖,一行做一個(gè)判斷對(duì)一組值要判斷 4 次,現(xiàn)在對(duì)一個(gè)列進(jìn)行數(shù)據(jù)的判斷。所以在數(shù)據(jù)庫(kù)的角度同樣也是對(duì)一個(gè)值的運(yùn)算轉(zhuǎn)化成對(duì)一組值的運(yùn)算。
02????Doris?如何實(shí)現(xiàn)向量化
接下來介紹 Apache Doris 如何實(shí)現(xiàn)向量化,這也是我們目前正在做的工作。實(shí)現(xiàn)向量化核心工作主要分為這三塊:-
列式存儲(chǔ): 在 Doris 的執(zhí)行引擎中引入基于列存的存儲(chǔ)格式。在執(zhí)行引擎當(dāng)中, Doris 現(xiàn)在存儲(chǔ)層的數(shù)據(jù)是以列存儲(chǔ)的,但是在執(zhí)行引擎當(dāng)中我們還是基于行的方式來做運(yùn)算的。我們前面看到那張圖是基于 Tuple 運(yùn)算的,每次只能運(yùn)算一個(gè)值,所以我們要把它替換為一個(gè)列式存儲(chǔ)的執(zhí)行引擎,這樣我們才能夠?qū)崿F(xiàn)向量化。
-
向量化函數(shù)計(jì)算框架 : 基于列式存儲(chǔ)重新設(shè)計(jì)一套向量化/列式計(jì)算引擎。在列式存儲(chǔ)的基礎(chǔ)上,我們要實(shí)現(xiàn)一套向量化的函數(shù)計(jì)算框架。基于現(xiàn)有的新的列式存儲(chǔ)格式,重新設(shè)計(jì)一套向量化列式存儲(chǔ)的計(jì)算引擎。
-
向量化算子 : 基于前兩者,重新組織SQL算子。基于列式存儲(chǔ)和向量化的函數(shù)計(jì)算框架,我們要實(shí)現(xiàn)所有的向量化算子,這一塊工程量其實(shí)是比較大的。
1.列式存儲(chǔ)
改變了計(jì)算引擎對(duì)數(shù)據(jù)的組織方式,由行存的 Tuple 與 RowBatch 變?yōu)榱?Column 與 Block原先 Doris 在執(zhí)行引擎當(dāng)中的數(shù)據(jù)內(nèi)存結(jié)構(gòu)是左邊的 RowBatch 結(jié)構(gòu),數(shù)據(jù)通過一個(gè)一個(gè) Tuple 進(jìn)行組織的,每一個(gè) Tuple 是個(gè)連續(xù)的內(nèi)存。我們可以看到左邊 RowBatch 的結(jié)構(gòu)分為三個(gè)列,但它每一個(gè)行是一個(gè)連續(xù)的內(nèi)存結(jié)構(gòu),在組織內(nèi)部處理當(dāng)中也是一行一行處理的。 右邊是我們新的結(jié)構(gòu) Block ,我們可以看到它的數(shù)據(jù)是按列來進(jìn)行組織的,每一個(gè)列是一個(gè)連續(xù)的內(nèi)存結(jié)構(gòu)。 2.向量化的函數(shù)計(jì)算框架 這里我簡(jiǎn)單舉一個(gè)例子
select a,abs(b) from test;
但是我們可以看下邊列存的執(zhí)行邏輯,相對(duì)行存的執(zhí)行邏輯更簡(jiǎn)潔。首先在整個(gè) ?Block 的執(zhí)行過程中只有一次類型判斷,我們可以看到假如 RawBatch 或者 ?Block 有 1024 行,原行存執(zhí)行結(jié)構(gòu)對(duì)于類型的判斷要走 1024 次,但對(duì)于列存來說只要一次就可以了,減少了大量類型判斷。另外,從代碼上可能不容易看出來其實(shí)每一次處理時(shí)列存是連續(xù)的,我們對(duì)連續(xù)的一段內(nèi)存做處理, Cache 親和度更高。 03????向量化計(jì)算優(yōu)點(diǎn) 相對(duì)于舊的行存計(jì)算框架,列式的函數(shù)計(jì)算框架有以下優(yōu)勢(shì):
-
Cache 更親和,列式計(jì)算由于數(shù)據(jù)是按列組織的,所以更容易命中 Cache 。 比如剛才的例子中,運(yùn)算 abs(b)?時(shí)沒有相關(guān)的列是不會(huì)參與到計(jì)算過程當(dāng)中來的。列式計(jì)算由于數(shù)據(jù)在列上連續(xù),所以更容易命中我們需要計(jì)算的 Cache ,從 Cache 中讀取數(shù)據(jù)和內(nèi)存中讀取數(shù)據(jù),性能有 10 倍至 100 倍的差距。
-
減少虛函數(shù)的調(diào)用,減少分支跳轉(zhuǎn),降低 CPU 分支預(yù)測(cè)判斷失敗概率。 從兩段代碼能明顯看到減少很多類型的判斷,在向量化框架當(dāng)中大量運(yùn)用模板的方式做零成本的抽象減少虛函數(shù)調(diào)用。關(guān)于虛函數(shù)調(diào)用會(huì)有什么開銷、引起什么問題,我們?cè)诤竺鏁?huì)再詳細(xì)討論。
- 函數(shù)計(jì)算的 SIMD ,包含編譯器自動(dòng) SIMD 與手動(dòng) Coding 的 SIMD指令集。 這一部分對(duì)應(yīng)一開始單獨(dú)提到的「從CPU角度去看向量化」,原先一次只能算一個(gè)值,現(xiàn)在向量化計(jì)算框架中一次可以計(jì)算多個(gè)值,這樣就會(huì)有數(shù)倍的性能提升。
這邊我列了下面這個(gè)表格。
2.虛函數(shù)調(diào)用的開銷。 虛函數(shù)帶來的開銷主要是下面兩點(diǎn): 2.1 ?虛函數(shù)的動(dòng)態(tài)調(diào)用是無(wú)法進(jìn)行函數(shù)內(nèi)聯(lián)的,這會(huì)大大減少編譯器可能進(jìn)行的優(yōu)化空間。 虛函數(shù)實(shí)際調(diào)用時(shí)需要查表,編譯器無(wú)法知道當(dāng)時(shí)動(dòng)態(tài)狀態(tài)下需要調(diào)用什么樣的函數(shù) ,所以沒有辦法進(jìn)行內(nèi)聯(lián)。我們知道函數(shù)內(nèi)聯(lián)真正意義就是給編譯器更多的優(yōu)化空間,這與數(shù)據(jù)庫(kù)當(dāng)中的優(yōu)化器是類似的,給更多的信息才能做更好的優(yōu)化。編譯器的角度也是同樣的道理,但因?yàn)樘摵瘮?shù)沒有辦法進(jìn)行函數(shù)內(nèi)聯(lián),所以編譯器獲取的信息就會(huì)大大減少,這樣編譯器代碼優(yōu)化空間就會(huì)減少。 2.2 ?虛函數(shù)查表帶來額外的分支跳轉(zhuǎn)的開銷,分支預(yù)測(cè)失敗會(huì)導(dǎo)致CPU流水線重新執(zhí)行。
分支跳轉(zhuǎn)在 CPU 當(dāng)中是有一定開銷的。下面這張圖是 Pipeline 的執(zhí)行流程,分為 Fetch , Decode , Executed , Write-back,這四個(gè) Stage 。現(xiàn)在的 CPU 還要比這個(gè)復(fù)雜很多。
一旦 CPU 進(jìn)入一個(gè)跳轉(zhuǎn)流程當(dāng)中,原則上來講 Pipeline 是要暫停下來的,因?yàn)樘D(zhuǎn)指令是依賴前一個(gè)指令執(zhí)行結(jié)果,完成后我們才能確定要執(zhí)行什么指令。但是現(xiàn)在 CPU 進(jìn)行分支預(yù)測(cè)不會(huì)讓流水線空轉(zhuǎn)。分支預(yù)測(cè)一旦成功的話,已經(jīng)順著流水線執(zhí)行下去的指令能夠得到很好的收益,但一旦分支預(yù)測(cè)失敗會(huì)導(dǎo)致 CPU 流水線重新執(zhí)行,這也會(huì)帶來極大的性能開銷 。 對(duì)于分支預(yù)測(cè),給大家舉個(gè)小例子,大家可以實(shí)際去用代碼去實(shí)踐一下。 假如我有個(gè) vector 存儲(chǔ)的指針對(duì)象有虛函數(shù)調(diào)用,我們是把不同的對(duì)象交替地放在這個(gè)
vector 當(dāng)中,還是把這個(gè) vector 基于對(duì)象類型做一次排序之后調(diào)用,哪個(gè)執(zhí)行效率更高,大家可以實(shí)際寫代碼去驗(yàn)證一下。有意思的是他們實(shí)現(xiàn)的匯編都是一模一樣,但是后者更快,這就是分支預(yù)測(cè)失敗帶來的一個(gè)影響。
3.函數(shù)執(zhí)行如何 SIMD 3.1 Auto?vectorized 自動(dòng)向量化,也就是編譯器自動(dòng)去分析 for 循環(huán)是否能夠向量化。GCC 開啟的 -O3 優(yōu)化便會(huì)開啟自動(dòng)向量化。 自動(dòng)向量化 tips : (1)足夠簡(jiǎn)單的 for 循環(huán)。
(2)足夠簡(jiǎn)單的代碼,避免:函數(shù)調(diào)用,分支跳動(dòng)。
(3)規(guī)避數(shù)據(jù)依賴,即避免下一個(gè)計(jì)算結(jié)果依賴上一個(gè)循環(huán)的計(jì)算結(jié)果。
(4)連續(xù)的內(nèi)存和對(duì)齊的內(nèi)存。SIMD 指令本身對(duì)于內(nèi)存要求是比較多的。首先前面我們講到了 CPU 是連續(xù)載入多個(gè)數(shù)據(jù)的,數(shù)據(jù)在不連續(xù)的內(nèi)存上沒有辦法一次做連續(xù)的載入。第二是內(nèi)存對(duì)齊會(huì)影響向量化指令的執(zhí)行效率。GCC 的文檔上給了一個(gè)比較完整的 case ,講到如何寫代碼編譯器能夠做自動(dòng)的向量化,大家有興趣的話可以參考 GCC 的文檔 CASE:
https://gcc.gnu.org/projects/tree-ssa/vectorization.html
如何確認(rèn)代碼編譯器的自動(dòng)向量化生效了呢? (1)編譯器的 Hint 提示。 -fopt-info-vec-all:打印所有編譯器進(jìn)行向量化的信息,如果循環(huán)代碼被向量化了,會(huì)打印如下信息 main.cpp:5: note: LOOP VECTORIZED. -fopt-info-vec-missed:沒有被向量化的原因 -fdump-tree-vect-all:進(jìn)一步分析沒有被向量化的原因 大家可以把 Hint ?提示打開,打開后就能在編譯的過程中看到編譯器的提示,如果循環(huán)代碼被向量化了,編譯器會(huì)打印對(duì)應(yīng)的信息。LOOP VECTORIZED 告訴你這個(gè)循環(huán)被向量化。如果是沒有被向量化的話可以打印 ?vec-missed 的 Hint ,它會(huì)告訴你為什么函數(shù)沒有被向量化,但通常只會(huì)提供一個(gè)簡(jiǎn)單的原因。如果要更深入分析的話,可以用最下面我給大家的 Hint 進(jìn)一步分析為什么沒有被向量化。大家可以實(shí)際寫代碼去實(shí)踐一下。 (2)直接通過 perf/objdump 查看生成的匯編代碼。 在一個(gè)大型程序上一個(gè)一個(gè)看 for 循環(huán)的話比較困難,我們可以把編譯出來的產(chǎn)出通過 perf 或 objdump 直接查看生成的匯編代碼,就可以看到有沒有向量化了。我這邊截了一張圖:
Doris?向量化的當(dāng)前情況
01????SQL 算子
在 0.15 版本我們發(fā)布了一個(gè)單表的向量化執(zhí)行引擎,能夠滿足大寬表的向量化查詢需求,實(shí)現(xiàn)向量化的 SQL 算子包括 Sort,Agg,Scan,Union。當(dāng)前 Doris 的數(shù)據(jù)存儲(chǔ)是基于列式存儲(chǔ),在數(shù)據(jù)進(jìn)來之后的一些計(jì)算過程是基于行存來進(jìn)行的,在 ScanNode 上轉(zhuǎn)成列式存儲(chǔ),基于列式存儲(chǔ)實(shí)現(xiàn)了這4種向量化的算子執(zhí)行向量化的計(jì)算。02????如何開啟向量化
1.設(shè)置環(huán)境變量?set enable_vectorized_engine = true;(必須) 我們可以看到這張圖,設(shè)置后的執(zhí)行計(jì)劃會(huì)帶一個(gè)v,這其實(shí)跟匯編指令生成 ?SIMD 指令集是相似的,代表開啟向量化。
2.設(shè)置環(huán)境變量set batch_size = 4096; (推薦)
我們?cè)趯?shí)際的測(cè)試當(dāng)中測(cè)試下來,?推薦設(shè)置 batch_size 為 4096 ,或者說在向量化當(dāng)中應(yīng)該講? Block 實(shí)測(cè)下來設(shè)置為 4096 行性能是最好的。當(dāng)然這里僅作推薦,不調(diào)整的話性能也還是不錯(cuò)的。
03????向量化的單表性能
這是 0.15 版本我們?cè)趩伪砩献龅囊恍y(cè)試,與原來行存做了一個(gè)對(duì)比。 Q1:select count(*) FROM lineorder_flat; Q2:select min(lo_revenue) as min_revenue from lineorder_flat group by c_nation; Q3:select count(distinct lo_commitdate), count(distinct lo_discount) from lineorder_flat;可以看到性能提升的效果還是比較可觀的。這是在 0.15 版本我們實(shí)測(cè)的向量化的性能,后續(xù)的版本性能會(huì)更激動(dòng)人心,值得大家期待!
Doris?向量化的未來規(guī)劃
接下來是向量化的未來規(guī)劃,包括功能的完善與發(fā)布,以及關(guān)于后續(xù)版本的想法,這部分我想也是大家最關(guān)心的。01????SQL 算子
Join 算子是 Doris 最為核心的算子,絕大多數(shù)場(chǎng)景使用 Doris 其實(shí)也是看中 Doris 本身在 MPP 場(chǎng)景下的多表? Join 能力,所以 Join 開發(fā)也是我們向量化開發(fā)當(dāng)中的重中之重。
可以告訴大家我們已經(jīng)實(shí)現(xiàn)了 Join 的向量化,只是還沒有做系統(tǒng)的調(diào)優(yōu)。這是我們基于 SSB測(cè)試集的 Join 向量化性能情況,這是第一版大家可以簡(jiǎn)單看一下,在 SSB 測(cè)試集當(dāng)中 Join 性能基本有 30% 至 40% 甚至 1 倍的提升。 剩下一些 SQL 算子,除了 Join 之外大家可能還會(huì)用到的:交集,差集, cross Join,ODBC/MySQL Scan Node,窗口函數(shù)(WIP),ES Scan Node(WIP)?,這些算子其實(shí)都是當(dāng)前 Doris 行存支持的SQL算子,除了部分算子還在開發(fā)中,基本都已經(jīng)全部 Ready,現(xiàn)在還在做一些穩(wěn)定性和性能調(diào)優(yōu)工作。
02? ? 存儲(chǔ)層向量化
前面講到目前 Doris 的數(shù)據(jù)是基于列存儲(chǔ)在磁盤上。但我們讀下來之后要對(duì)這個(gè)數(shù)據(jù)做聚合,這個(gè)過程是通過行存來表示的。這部分因?yàn)闅v史原因存在了很多冗余低效的代碼,目前我們?cè)趯?shí)際的向量化開發(fā)中發(fā)現(xiàn)已經(jīng)嚴(yán)重影響了整個(gè)向量化代碼的執(zhí)行邏輯與性能。主要是如下幾個(gè)問題: 1.計(jì)算表達(dá)式受限制。 很多計(jì)算表達(dá)式因?yàn)閮?nèi)存結(jié)構(gòu)不同、接口不同沒有辦法作用于存儲(chǔ)層,導(dǎo)致表達(dá)式?jīng)]有辦法下推,以及無(wú)法做向量化的計(jì)算。 2.額外的轉(zhuǎn)換的性能開銷比較嚴(yán)重, 嚴(yán)重影響到導(dǎo)入和查詢性能。我們實(shí)際做了一個(gè) POC 的測(cè)試,在 DupKey 表上通過完整的向量化改造性能還能有10倍級(jí)別的提升。 3.代碼可維護(hù)性降低。 因?yàn)榻Y(jié)構(gòu)不同,所以目前Doris 在執(zhí)行引擎實(shí)現(xiàn)的聚合算子沒有辦法作用于存儲(chǔ)引擎。同樣的聚合代碼要在存儲(chǔ)層和查詢層,也就是存儲(chǔ)引擎和查詢引擎分別實(shí)現(xiàn),代碼可維護(hù)性就很差。另外在查詢層進(jìn)行性能優(yōu)化沒有辦法作用在存儲(chǔ)層下,性能優(yōu)化需要考慮兩部分,所以也帶來了一些問題。我們目前在做的一個(gè)很重要的工作就是把 Doris存儲(chǔ)層通過行存做去重聚合的邏輯進(jìn)行向量化。
03? ? 導(dǎo)入向量化
?前 Doris 進(jìn)行數(shù)據(jù)導(dǎo)入時(shí)存在 Tuple 轉(zhuǎn) RowCursor ,數(shù)據(jù)行式聚合等一系列有冗余開銷的工作。而我們后續(xù)希望通過導(dǎo)入向量化的開發(fā)實(shí)現(xiàn):
- 減少額外內(nèi)存格式的轉(zhuǎn)換開銷,提高 CPU 的利用率
- 復(fù)用計(jì)算層的算子,減少冗余低效的代碼,簡(jiǎn)潔 Doris 現(xiàn)有的代碼結(jié)構(gòu)
- 利用 SIMD 加快導(dǎo)入過程當(dāng)中的聚合計(jì)算,進(jìn)一步提升 Doris 導(dǎo)入性能
目前向量化版本實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的導(dǎo)入框架。Block 計(jì)算完成之后是以列組織的,通過向量化的計(jì)算引擎做格式的轉(zhuǎn)化,但最終在發(fā)送數(shù)據(jù)時(shí),由于接收端還沒有做向量化改造,所以我們現(xiàn)在還是基于 RowBatch 的數(shù)據(jù)格式進(jìn)行數(shù)據(jù)發(fā)送。下一步我們要規(guī)劃的工作就是把通過 Tuple 轉(zhuǎn) Rowcursor 進(jìn)行運(yùn)算這部分全部剔除掉,轉(zhuǎn)換成向量化的格式或者說列存的格式進(jìn)行運(yùn)算。
04? ??SQL函數(shù)
1.函數(shù)豐富度支持 前面講到了目前 Doris 已有的函數(shù)是比較豐富的,但是因?yàn)橄蛄炕腔诹写鎸?shí)現(xiàn)的,函數(shù)接口包括調(diào)用的方式都有所不同,所以我們不單單要實(shí)現(xiàn) SQL 算子,還要實(shí)現(xiàn)浩如煙海的 SQL 函數(shù)。目前我們已經(jīng)實(shí)現(xiàn)了向量化支持的函數(shù)大概有 200 多個(gè),其他還在不斷的開發(fā)過程當(dāng)中,需要盡快補(bǔ)齊原先行存支持但是向量化還沒有支持的函數(shù)。這部分工作也歡迎大家參與進(jìn)來。2.函數(shù)的 SIMD 化
我們保證在列存上能夠利用前面提到的幾個(gè)優(yōu)勢(shì)使分支跳轉(zhuǎn)變少,Cache 親和度更高。但目前很多實(shí)現(xiàn)向量化的函數(shù)沒有考慮 SIMD 化。尤其對(duì)于熱點(diǎn)的核心函數(shù),我們后續(xù)規(guī)劃盡量通過各種可能的方式進(jìn)行 SIMD 化,包括我們前面提到手寫 SIMD 。我自己在開發(fā)過程當(dāng)中手寫了一些 SIMD 的函數(shù)。目前在 Apache 的 Master 庫(kù)也能看到我自己手寫的一些在字符串實(shí)現(xiàn)的SIMD 的函數(shù)。3.向量化的 UDF 的框架設(shè)計(jì)和實(shí)現(xiàn)。
UDF 也是大家經(jīng)常用到一個(gè)功能,向量化上需要重新設(shè)計(jì)一個(gè) UDF 框架,這也是我們后續(xù)要做的。
05? ??代碼重構(gòu)
1.基礎(chǔ)類型的重構(gòu) 。目前 Doris 向量化上所有的數(shù)據(jù)類型都能夠支持,但是有這幾個(gè)問題:-
Data / Datatime:更小的內(nèi)存占用,對(duì) SIMD 更友好的內(nèi)存布局。 Doris 現(xiàn)在的 Data 和 DataTime 類型復(fù)用了行存,毫秒的數(shù)據(jù)其實(shí)在現(xiàn)在的 Doris 當(dāng)中沒有在用了。 現(xiàn)在 Data 和 DataTime 占用 16 字節(jié),而毫秒就占了 8 字節(jié),這八字節(jié)完全沒有用到,額外占用了很大的內(nèi)存。 這部分內(nèi)存占用在原來函數(shù)當(dāng)中還不明顯,但在向量化當(dāng)中8個(gè)字節(jié)的占用就會(huì)帶來很大的內(nèi)存開銷,對(duì) SIMD 不友好。 另外目前 Data / DataTime 內(nèi)存布局還有待優(yōu)化,在做 SIMD 時(shí)會(huì)有各種各樣的問題。 所以我們準(zhǔn)備重構(gòu) Data / DataTime,實(shí)現(xiàn)在向量化版本有更小的內(nèi)存占用,對(duì) SIMD 更友好的內(nèi)存布局。
-
Decimal:根據(jù)精度切換內(nèi)存占用,解決 Doris 中當(dāng)前精度浪費(fèi)的問題。 當(dāng)前的Doris在精度上沒有根據(jù)實(shí)際用戶設(shè)置的精度切換內(nèi)存占用,統(tǒng)一占用 16 字節(jié)的內(nèi)存,造成很大一部分開銷。 我們準(zhǔn)備對(duì) Decimal 的這一問題進(jìn)行重構(gòu)。
- HLL:減少 HLL 類型無(wú)效的序列化的開銷。 目 前我們已經(jīng)把 Bitmap 重構(gòu)完成,用了一個(gè)新的結(jié)構(gòu)表示 Bitmap ,減少了大量的序列化開銷,整體性能表現(xiàn)也很不錯(cuò)。 減少 HLL 在計(jì)算時(shí)無(wú)效的序列化開銷就是下個(gè)階段我們要做的事情。
寫在最后
01? ? 感謝 Clickhouse 社區(qū) Doris 在進(jìn)行向量化代碼開發(fā)時(shí),在列存模型和函數(shù)框架上引用了部分 Clickhouse 19.16.2.2 版本的代碼,我們?cè)谝么a的 License 上注明了相應(yīng)的工作,同時(shí)與 Clickhouse 社區(qū)進(jìn)行了對(duì)應(yīng)的溝通。十分感謝 Clickhouse 在 Doris 向量化代碼開發(fā)上給予的幫助。
02?? ?版本發(fā)布 如果順利的話 1 月底或 2 月初我們就會(huì)帶來下一版的向量化執(zhí)行引擎了,前面所提到的很多后續(xù)規(guī)劃內(nèi)容將在下一版本中落地。希望大家屆時(shí)多多試用捧場(chǎng)~
—— End ——
歡迎關(guān)注:
Apache Doris(incubating)官方公眾號(hào)
社區(qū)人物志|魏祚:道阻且長(zhǎng),行則將至,做有溫度的開源項(xiàng)目
從NoSQL到Lakehouse,Apache Doris的13年技術(shù)演進(jìn)之路
相關(guān)鏈接:
Apache Doris官方網(wǎng)站:
http://doris.incubator.apache.org
Apache?Doris?Githu b:
https://github.com/apache/incubator-doris
Apache Doris 開發(fā)者郵件組:
dev@doris.apache.org
本文分享自微信公眾號(hào) - ApacheDoris(gh_80d448709a68)。
如有侵權(quán),請(qǐng)聯(lián)系 support@oschina.cn 刪除。
本文參與“ OSC源創(chuàng)計(jì)劃 ”,歡迎正在閱讀的你也加入,一起分享。
總結(jié)
以上是生活随笔為你收集整理的活动回顾|Apache Doris 向量化技术实现与后续规划的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 王阳明《没有秘密的你》开播 超A男神化身
- 下一篇: 【8583】ISO8583各域段的说明