掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
?譯者 | 李睿

創(chuàng)新互聯(lián)建站服務(wù)項(xiàng)目包括前進(jìn)網(wǎng)站建設(shè)、前進(jìn)網(wǎng)站制作、前進(jìn)網(wǎng)頁(yè)制作以及前進(jìn)網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,前進(jìn)網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到前進(jìn)省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
審校 | 孫淑娟
提高分析性能非常重要。大家都明白這一點(diǎn),但要確保用戶在不增加額外工作量的情況下獲得所需的速度,最好的方法是什么?
作為數(shù)據(jù)工程師,通常面臨著這個(gè)挑戰(zhàn)。為了找到解決方案,一個(gè)研究團(tuán)隊(duì)啟動(dòng)了開(kāi)放項(xiàng)目StarRocks,這是一個(gè)分析引擎,可以滿足快速增長(zhǎng)的分析性能需求,同時(shí)也易于使用和維護(hù)。
隨著開(kāi)放項(xiàng)目和技術(shù)社區(qū)在過(guò)去幾年的發(fā)展,人們已經(jīng)了解到很多關(guān)于分析性能的有效方法和無(wú)效方法。如今分享一些關(guān)于構(gòu)建高性能分析引擎的關(guān)鍵技術(shù)之一的見(jiàn)解:向量化。
在深入研究StarRocks如何實(shí)現(xiàn)向量化之前,有一點(diǎn)很重要:當(dāng)談?wù)撓蛄炕瘯r(shí),談?wù)摰氖鞘褂矛F(xiàn)代CPU架構(gòu)的數(shù)據(jù)庫(kù)的向量化。有了這些了解,就可以開(kāi)始回答這個(gè)問(wèn)題:為什么向量化可以提高數(shù)據(jù)庫(kù)性能?
要回答這個(gè)問(wèn)題,首先要回答以下幾個(gè)問(wèn)題:
(1)如何衡量CPU性能?
(2)影響CPU性能的因素有哪些?
第一個(gè)問(wèn)題的答案可以用這個(gè)公式表示:
CPU時(shí)間=(指令數(shù))*CPI*(時(shí)鐘周期時(shí)間)
這個(gè)公式提供了一些術(shù)語(yǔ),可以用來(lái)討論影響性能的杠桿。由于對(duì)時(shí)鐘周期時(shí)間無(wú)能為力,所以需要關(guān)注指令號(hào)和CPI來(lái)提高軟件性能。
此外,還知道的另一個(gè)重要信息是,CPU指令的執(zhí)行可以分為五個(gè)步驟:
(1)提取
(2)解碼
(3)執(zhí)行
(4)內(nèi)存訪問(wèn)
(5)寫(xiě)回結(jié)果(寫(xiě)入寄存器)
步驟1和步驟2由CPU前端執(zhí)行,步驟3到步驟5由CPU后端處理。Intel公司發(fā)布了自頂向下微架構(gòu)分析方法,如下圖所示。
自頂向下微架構(gòu)分析方法(Intel)
下面是上述方法的簡(jiǎn)化版本。
正如人們所看到的,導(dǎo)致CPU性能問(wèn)題的主要因素是退役、錯(cuò)誤猜測(cè)、前端綁定和后端綁定。
這些問(wèn)題背后的主要驅(qū)動(dòng)因素分別是缺乏SIMD指令優(yōu)化、分支預(yù)測(cè)錯(cuò)誤、指令緩存失誤和數(shù)據(jù)緩存失誤。
因此,如果將上述原因映射到前面介紹的CPU性能公式,可以得到以下結(jié)論:
那么,設(shè)計(jì)什么來(lái)提高這四個(gè)方面的CPU性能呢?
沒(méi)錯(cuò),是向量化。
現(xiàn)在已經(jīng)確定了向量化可以提高數(shù)據(jù)庫(kù)性能。下面將講解向量化是如何做到這一點(diǎn)。
如果已經(jīng)很好地理解了向量化,那么可以跳過(guò)這一節(jié),然后轉(zhuǎn)到關(guān)于數(shù)據(jù)庫(kù)向量化的一節(jié),但是如果不熟悉向量化的基礎(chǔ)知識(shí),或者可能需要復(fù)習(xí)一下,那么將簡(jiǎn)要概述應(yīng)該知道的內(nèi)容。
在這里將向量化的討論局限于SIMD。SIMD向量化不同于接下來(lái)將要討論的一般數(shù)據(jù)庫(kù)向量化。
SIMD的意思是“單指令、多數(shù)據(jù)”。顧名思義,使用SIMD架構(gòu),一條指令可以同時(shí)操作多個(gè)數(shù)據(jù)點(diǎn)。在SISD(單指令、單數(shù)據(jù))架構(gòu)中,其中一條指令只能在單個(gè)數(shù)據(jù)點(diǎn)上操作,但情況并非如此。
如上所述,在SISD架構(gòu)中,操作是標(biāo)量的,這意味著只處理一組數(shù)據(jù)。因此,4個(gè)添加操作將涉及8個(gè)加載操作(每個(gè)變量一個(gè))、4個(gè)添加操作和4個(gè)存儲(chǔ)操作。如果使用128位SIMD,只需要兩個(gè)加載,一個(gè)添加,一個(gè)存儲(chǔ)。在理論上,與SISD相比,性能提高了4倍。考慮到現(xiàn)代CPU已經(jīng)有512位寄存器,可以預(yù)期高達(dá)16倍的性能增益。
以上了解了SIMD向量化如何極大地提高程序的性能。那么,如何開(kāi)始在自己的工作中使用它呢?
調(diào)用SIMD的不同方法
正如英特爾公司的這張圖片所示,SIMD有六種調(diào)用方式。從上到下,每個(gè)方法都需要程序員更多的專業(yè)知識(shí),并需要更多的編碼工作。
方法1.編譯器自動(dòng)向量化
程序員不需要對(duì)他們的代碼做任何更改。編譯器將自動(dòng)將標(biāo)量代碼轉(zhuǎn)換為向量代碼。只有一些簡(jiǎn)單的情況可以自動(dòng)轉(zhuǎn)換為向量代碼。
方法2.給編譯器的提示
在這個(gè)方法中,向編譯器提供了一些提示。通過(guò)提供額外的信息,編譯器可以生成更多的SIMD代碼。
方法3.并行編程API
在OpenMP或Intel TBB等并行編程API的幫助下,開(kāi)發(fā)人員可以添加Pragma來(lái)生成向量代碼。
方法4.使用SIMD類庫(kù)
這些庫(kù)包裝了啟用SIMD指令的類。
方法5.使用SIMD intrinsic
intrinsic是一組程序集編碼的函數(shù),允許使用c++函數(shù)調(diào)用和變量來(lái)代替程序集指令。
方法6.直接編寫(xiě)程序集代碼
1和方法2。對(duì)于不能自動(dòng)轉(zhuǎn)換為向量代碼的性能關(guān)鍵操作,將使用SIMD intrinsic。
這里有一個(gè)重要的問(wèn)題,當(dāng)一個(gè)程序有一個(gè)復(fù)雜的代碼結(jié)構(gòu),那么如何確保代碼執(zhí)行是向量化的?
有兩種方法可以檢查和確認(rèn)代碼已經(jīng)向量化。
方法1.向編譯器添加選項(xiàng)
有了這些選項(xiàng),編譯器將生成關(guān)于代碼是否向量化的輸出,如果沒(méi)有,原因是什么。例如,可以在GCC編譯器中添加--fopt-info-vec-all, -fopt-info-vec-optimized, -fopt-info-vec-missed, 和 -fopt-info-vec-note選項(xiàng),如下圖所示:
方法2.檢查執(zhí)行的程序集代碼
可以使用https://gcc.godbolt.org/這樣的網(wǎng)站或Perf和Vtun這樣的工具來(lái)檢查程序集代碼。如果匯編代碼中的寄存器是xmm、ymm、zmm等,或者指令以v開(kāi)頭,那么就知道該代碼已經(jīng)向量化了。
既然已經(jīng)掌握了向量化的基礎(chǔ)知識(shí),現(xiàn)在是時(shí)候討論向量化數(shù)據(jù)庫(kù)提高性能的能力了。
雖然StarRocks項(xiàng)目已經(jīng)發(fā)展成為一個(gè)成熟、穩(wěn)定、行業(yè)領(lǐng)先的MPP數(shù)據(jù)庫(kù)(甚至還從CelerData推出了企業(yè)級(jí)版本),但該社區(qū)必須克服許多挑戰(zhàn)才能實(shí)現(xiàn)這一目標(biāo)。數(shù)據(jù)庫(kù)向量化是最大的突破之一,也是最大的挑戰(zhàn)之一。
根據(jù)經(jīng)驗(yàn),向量化數(shù)據(jù)庫(kù)要比簡(jiǎn)單地在CPU中啟用SIMD指令復(fù)雜得多。這是一個(gè)龐大的系統(tǒng)工程。特別是面臨著六個(gè)技術(shù)挑戰(zhàn):
(1)端到端的柱狀數(shù)據(jù)。數(shù)據(jù)需要跨存儲(chǔ)層、網(wǎng)絡(luò)層和內(nèi)存層以柱狀格式存儲(chǔ)、傳輸和處理,以消除“阻抗失配”。存儲(chǔ)引擎和查詢引擎需要重新設(shè)計(jì)以支持列數(shù)據(jù)。
(2)所有運(yùn)算符、表達(dá)式和函數(shù)都必須實(shí)現(xiàn)向量化。這是一項(xiàng)艱巨的任務(wù),需要幾年才能完成。
(3)如果可能,操作符和表達(dá)式應(yīng)該調(diào)用SIMD指令。這需要詳細(xì)的逐行優(yōu)化。
(4)內(nèi)存管理。為了充分利用SIMD CPU的并行處理能力,必須重新考慮內(nèi)存管理。
(5)新的數(shù)據(jù)結(jié)構(gòu)。所有用于核心操作符的數(shù)據(jù)結(jié)構(gòu),如連接、聚合、排序等,都需要從頭開(kāi)始支持向量化。
(6)系統(tǒng)的優(yōu)化。對(duì)StarRocks的目標(biāo)是,與其他市場(chǎng)領(lǐng)先的產(chǎn)品(具有相同的硬件配置)相比,性能提高5倍。為了達(dá)到這個(gè)目標(biāo),必須確保數(shù)據(jù)庫(kù)系統(tǒng)中的所有組件都得到了優(yōu)化。
在向量化StarRocks時(shí),大部分工程工作都花在向量化操作符和表達(dá)式上。這些工作可以總結(jié)為按列批量計(jì)算,如下圖所示:
與本文前面討論的Intel公司自頂向下微架構(gòu)分析方法相對(duì)應(yīng),Batch減少了分支錯(cuò)誤預(yù)測(cè)和指令緩存失誤。按列減少了數(shù)據(jù)緩存丟失,并使調(diào)用SIMD優(yōu)化更容易。
實(shí)現(xiàn)批處理計(jì)算相對(duì)容易。困難的部分是關(guān)鍵操作符(如聯(lián)接、聚合、排序和混洗)的列處理。在進(jìn)行柱狀處理的同時(shí)調(diào)用盡可能多的SIMD優(yōu)化是一個(gè)更大的挑戰(zhàn)。
如上所述,向量化數(shù)據(jù)庫(kù)是一項(xiàng)系統(tǒng)工程工作。在過(guò)去的幾年里,在開(kāi)發(fā)StarRocks的過(guò)程中實(shí)施了數(shù)百項(xiàng)優(yōu)化。以下是需要關(guān)注的7個(gè)最重要的優(yōu)化領(lǐng)域。
如下圖所示,通過(guò)操作將兩個(gè)基于字符串的組轉(zhuǎn)換為一個(gè)基于整數(shù)的組。因此,掃描、散列、相等和mumcpy等操作的性能提高了許多倍,整體查詢性能提高了300%以上。
下面的代碼片段顯示了一個(gè)基于選擇率動(dòng)態(tài)選擇連接運(yùn)行時(shí)過(guò)濾器的示例:
有三個(gè)決策點(diǎn)可以指導(dǎo)上述示例:
(1)如果過(guò)濾器不能過(guò)濾大部分?jǐn)?shù)據(jù),那么就不會(huì)使用它。
(2)如果一個(gè)過(guò)濾器可以過(guò)濾幾乎所有的數(shù)據(jù),那么我們只保留這個(gè)過(guò)濾器。
(3)最多保留三個(gè)過(guò)濾器。
使用StarRocks,實(shí)現(xiàn)了一個(gè)列池?cái)?shù)據(jù)結(jié)構(gòu)來(lái)重用列的內(nèi)存,并顯著提高了查詢性能。以下的代碼片段顯示了一個(gè)HLL(HyperLogLog)聚合函數(shù)內(nèi)存優(yōu)化。通過(guò)按塊分配HLL內(nèi)存,并通過(guò)重用這些塊,將HLL的聚合性能提高了五倍。
在調(diào)用SIMD優(yōu)化和性能瓶頸從CPU限制轉(zhuǎn)移到內(nèi)存限制之后,CPU緩存缺失成為了一個(gè)特別重要的因素。下面的代碼片段展示了如何通過(guò)預(yù)取減少CPU丟失。不過(guò)在這里指出的是,預(yù)取應(yīng)該是優(yōu)化CPU緩存的最后手段。這是因?yàn)楹茈y控制預(yù)取的時(shí)間和距離。
現(xiàn)在已經(jīng)踏上了StarRocks數(shù)據(jù)庫(kù)向量化的旅程,以下回顧一下學(xué)到了什么。
隨著數(shù)據(jù)量的增長(zhǎng)、數(shù)據(jù)源的擴(kuò)展和用戶期望的提高,數(shù)據(jù)工程師的角色在未來(lái)幾年只會(huì)變得更加重要。有了StarRocks這樣的項(xiàng)目和數(shù)據(jù)庫(kù)向量化這樣的創(chuàng)新,可以滿足遇到的任何性能需求。
原文標(biāo)題:??How vectorization improves database performance???,作者:James Li,Kaisen Kang?

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流