進(jìn)迭時(shí)空專注于研發(fā)基于RISC-V的高性能新AI CPU,對于充分發(fā)揮CPU核的性能而言,編譯器是不可或缺的一環(huán),而在AI時(shí)代,毫無疑問向量算力將發(fā)揮越來越重要的作用。進(jìn)迭時(shí)空非常重視RISC-V高性能算力生態(tài)的建設(shè),正投入編譯器自動(dòng)向量化優(yōu)化等多項(xiàng)關(guān)鍵技術(shù),全面助力RISC-V的高性能發(fā)展。
RISC-V 向量設(shè)計(jì)
SpacemiT
在現(xiàn)代CPU中,向量支持是算力的一個(gè)重要組成部分。1996年Intel就推出了針對多媒體應(yīng)用程序設(shè)計(jì)的SIMD指令集MMX,隨后又逐步引入了SSE、AVX、AVX2、AVX-512,Arm也引入了NEON指令集支持,并在armv8版本中將NEON定義為默認(rèn)支持,后續(xù)又引入了長度可變的SVE。
對于新興的RISC-V架構(gòu), 同樣也有vector擴(kuò)展支持。RISC-V Vector Extension(下文簡稱RVV)是 RISC-V 指令集架構(gòu)(ISA)中的一種擴(kuò)展,專門設(shè)計(jì)用于高效的向量處理。RVV 為RISC-V 指令集架構(gòu)引入了強(qiáng)大的向量處理能力,旨在通過向量化計(jì)算提高多種應(yīng)用程序的計(jì)算性能。
吸收了其他架構(gòu)的經(jīng)驗(yàn),RISC-V發(fā)現(xiàn)傳統(tǒng)的SIMD指令設(shè)計(jì)并不夠好,不同的寬度引入不同的SIMD指令,使得整個(gè)指令集越來越龐大和復(fù)雜。RISC-V的發(fā)明人Patterson教授在《SIMD Instructions Considered Harmful》一文中闡述了這一觀點(diǎn)。
最終RVV的設(shè)計(jì)更類似于SVE,是可變長的向量,而且非常靈活,可在運(yùn)行時(shí)動(dòng)態(tài)設(shè)置寄存器大小,分組,寬度,以及掩碼操作等,可以做到同一份二進(jìn)制文件在不同VLEN的硬件上都能充分發(fā)揮硬件性能。
其靈活的設(shè)計(jì)和易于編程的特性,使其在現(xiàn)代計(jì)算任務(wù)中具有明顯的優(yōu)勢,并為未來的計(jì)算需求提供了良好的支持。隨著 RISC-V 生態(tài)系統(tǒng)的發(fā)展,RVV 有望在更多應(yīng)用中發(fā)揮重要作用。
自動(dòng)向量化
SpacemiT
如何利用向量算力,一種方式是軟件開發(fā)者直接調(diào)用向量的編程接口,另一種方式是直接編寫標(biāo)量代碼通過編譯器實(shí)現(xiàn)自動(dòng)向量化,這兩種方式各有優(yōu)劣,都不可或缺。
向量化(Vectorization)是一種編程和編譯優(yōu)化技術(shù),自動(dòng)向量化的本質(zhì)是編譯器識別程序中的循環(huán)或者基本塊,將多個(gè)標(biāo)量操作組合在一起,利用編譯器數(shù)據(jù)流/控制流等分析技術(shù)自動(dòng)生成SIMD/向量指令的過程,以此達(dá)到提高數(shù)據(jù)并行,加快數(shù)據(jù)計(jì)算的目的。
由于其在科學(xué)計(jì)算、圖像處理、機(jī)器學(xué)習(xí)和數(shù)字信號處理等領(lǐng)域具有廣泛的應(yīng)用,使得業(yè)界對向量化這項(xiàng)技術(shù)一直有持續(xù)的關(guān)注和投入,主要是因?yàn)槭亲詣?dòng)向量化可以帶來很多優(yōu)勢:
性能提升:自動(dòng)向量化利用硬件架構(gòu)提供的SIMD/Vector指令,減少了迭代循環(huán)的開銷,且提高數(shù)據(jù)并行處理的能力,對計(jì)算密集或者數(shù)據(jù)規(guī)模大的場景會(huì)帶來極大的性能優(yōu)勢。
降低編程的復(fù)雜性:開發(fā)者不需要手動(dòng)編寫復(fù)雜的向量化代碼,交給編譯器自動(dòng)分析、優(yōu)化和生成向量代碼。
兼容性和可移植性:通過自動(dòng)向量化,開發(fā)者可以編寫標(biāo)準(zhǔn)的標(biāo)量代碼運(yùn)行在不同的平臺,編譯器會(huì)根據(jù)目標(biāo)平臺特性生成可在對應(yīng)平臺上執(zhí)行的向量代碼。

自動(dòng)向量化實(shí)現(xiàn)
SpacemiT
自動(dòng)向量化工具
目前LLVM框架下支持的自動(dòng)向量化工具有 SLP Vectorize 和 Loop Vectorize。
SLP Vectorize(superword-level parallelism)
SLP向量化關(guān)注單次迭代間的向量化機(jī)會(huì),在基本塊中搜集相似的標(biāo)量指令,通過將相似標(biāo)量指令合并為向量指令的方式,來實(shí)現(xiàn)向量化。如下程序可以通過構(gòu)造向量(a1, a2)和 (b1, b2),完成向量化算術(shù)運(yùn)算。
void foo(int a1, int a2, int b1, int b2, int *A) { A[0] = a1*(a1 + b1); A[1] = a2*(a2 + b2); A[2] = a1*(a1 + b1); A[3] = a2*(a2 + b2); }
Loop Vectorize
循環(huán)向量化關(guān)注循環(huán)迭代間的向量化機(jī)會(huì),將多次迭代處理的數(shù)據(jù)利用更寬的位寬寄存器存儲,使其一次能夠完成多次循環(huán)迭代的數(shù)據(jù)處理,此后每次循環(huán)迭代的下標(biāo)步長將擴(kuò)寬成SIMD的位寬/向量元素的位寬。
for (int i = 0; i < n; i++) { ? A[i] = B[i] + C[i] } -----> Transform for (int i = 0; i < n; i = i + step) { ? // 結(jié)合tail Folding 機(jī)制 和 Loop unroll 完成自動(dòng)向量化的過程 ? for (int j = i; j < min(n, i + step); j++) { ? ? A[j] = B[j] + C[j]; ? } }
Loop Vectorize 優(yōu)化介紹
循環(huán)中的標(biāo)量代碼是否可以向量化,主要涉及到以下三個(gè)階段:
檢查當(dāng)前循環(huán)是否可以向量化,對其合法性進(jìn)行校驗(yàn);
在滿足合法性校驗(yàn)的前提下,利用代價(jià)模型分析向量化的代碼是否具有收益;
確定向量化代碼可以帶來收益,完成標(biāo)量代碼轉(zhuǎn)換為向量代碼,并更新當(dāng)前循環(huán)控制流。
下文會(huì)對Loop Vectorize 進(jìn)行簡要介紹(更多細(xì)節(jié)可以查閱文末的參考文檔):
Loop Vectorize VPlan 架構(gòu)介紹
VPlan 是LLVM Loop Vectorize 基礎(chǔ)設(shè)施的重要組成部分, 其主要是為編譯器在Loop Vectorize 分析中獲取到的所有向量化因子(VF)進(jìn)行建模和評估,根據(jù)代價(jià)模型,選擇成本最優(yōu)的向量化模型,并進(jìn)行轉(zhuǎn)換,其存儲了所有可能的向量化候選者代碼,使得Loop Vectorize 實(shí)現(xiàn)更模塊化,也增強(qiáng)了其可擴(kuò)展性,為復(fù)雜控制流和內(nèi)存訪問循環(huán)提供了更多向量化的機(jī)會(huì)。
整個(gè)LLVM Loop Vectorize是基于VPlan架構(gòu)實(shí)現(xiàn)的。其在輸入和輸出中間加了一層VPlan層,將IR層面的轉(zhuǎn)換和分析隔離,可以有效地簡化數(shù)據(jù)流的分析,僅需更新VPlan IR to Output IR 的控制流信息(增加了產(chǎn)生向量化的代碼的機(jī)會(huì)),主要有以下流程:
Input IR to VPReciple IR:通過合法性分析 + TTI 對應(yīng)的目標(biāo)平臺后端提供的代價(jià)模型獲取最優(yōu)VF,并將結(jié)果存儲到VPlan中,完成首次VPlan model 的構(gòu)建,此時(shí)無需更新控制流。
VPlan-to-VPlan Transform Pipeline:在獲取VPlan 之后,針對一些場景做優(yōu)化,例如冗余Recipe 刪除、簡化Vector Region 實(shí)現(xiàn)(循環(huán)條件或者循環(huán)歸納變量的優(yōu)化)和插入EVL等。
VPRecipe IR to Output IR:利用VPTransformState中提供的信息存儲和吐出Output IR,生成真正的vectorizing code,此時(shí)需要重新調(diào)整循環(huán)結(jié)構(gòu)并更新控制流。
Loop Vectorize 實(shí)現(xiàn)方式
LLVM 在Loop Vectorize 中的實(shí)現(xiàn)主要有以下兩種方式:Vector Length Specific 和 Vector Length Agnostic 。下文會(huì)重點(diǎn)講解這兩個(gè)方案的優(yōu)劣勢并通過如下用例展示效果。
void vp_add(int *restrict a, int *restrict b, int *restrict c, int N) { for (int i = 0; i < N; i++) { ? ?a[i] = b[i] + c[i]; ?}}
Vector Length Specific (VLS)
編譯器在Loop Vectorize優(yōu)化階段直接利用硬件的向量寄存器位寬進(jìn)行向量化。如果當(dāng)前存在尾部元素沒辦法填滿向量寄存器,則使用標(biāo)量的方式處理尾部元素。
優(yōu)勢:
目前,Loop Vectorize架構(gòu)已經(jīng)實(shí)現(xiàn)且無需特殊的 IR-Level Express。
劣勢:
需要單獨(dú)處理循環(huán)尾序。
沒充分利用RVV Scalable的特性,其生成的二進(jìn)制只能在指定的VLEN 架構(gòu)上運(yùn)行。
編譯選項(xiàng)
clang --target=riscv64 -march=rv64imav -mllvm -riscv-v-vector-bits-min=128 -mllvm -riscv-v-vector-bits-max=128 -O3 -S xxx.c -o xxx.s
匯編效果
注:用于向量配置的 vsetivli 指令是位于向量循環(huán) .LBB0_4 的外部。在向量循環(huán)結(jié)束后,還需要一個(gè)額外的標(biāo)量循環(huán) .LBB0_7 處理尾部元素。
Vector Length Agnostic(VLA)
最近幾年,LLVM 引入了 Vector Predication IR (VP IR),其VP IR中攜帶的參數(shù)Mask 和 EVL(Explicit Vector Length)為獨(dú)立于目標(biāo)平臺的各個(gè)架構(gòu)提供了豐富的predicated vector instructions。當(dāng)前,編譯器在Loop Vectorize優(yōu)化階段的VLA 方案也是使用VP IR作為IR-Level Express完成的。編譯器在循環(huán)迭代中,將所有 vector instructions 替換為predicated vector instructions,并使用EVL設(shè)置每次迭代需要處理的向量元素長度(RISC-V 架構(gòu)會(huì)在后續(xù)Lowering階段翻譯成RVV vsetvli/vsetvl/vsetivli 指令)。
優(yōu)勢:
充分利用RVV 的Scalable 特性,其生成的二進(jìn)制可以在任何VLEN架構(gòu)上運(yùn)行。
無需單獨(dú)處理循環(huán)尾序和條件分支。
劣勢:
需要特殊的 IR-Level Express(不過目前RVV VP的設(shè)計(jì)和慢慢趨于穩(wěn)定,積極推進(jìn)了Loop Vectorize在此方案的實(shí)現(xiàn))。
所有的vector instructions都帶有predicate標(biāo)識,且CFG也是,這對于分支預(yù)測率比較高或者條件分支執(zhí)行的概率很低的場景,可能會(huì)帶來負(fù)向性能收益。
編譯選項(xiàng)
clang --target=riscv64 -march=rv64imav -mllvm -force-tail-folding-style=data-with-evl -mllvm -prefer-predicate-over-epilogue=predicate-dont-vectorize -O3 -S xxx.c -o xxx.s
匯編效果
注:用于向量配置的 vsetvli 是位于向量循環(huán).LBB0_2的內(nèi)部,每次都會(huì)動(dòng)態(tài)設(shè)置處理的元素個(gè)數(shù),達(dá)到的效果是向量循環(huán)之后整個(gè)函數(shù)就結(jié)束了,無需再有額外的代碼處理尾部元素。
未來的重點(diǎn)工作方向
SpacemiT
進(jìn)迭時(shí)空當(dāng)前已經(jīng)發(fā)布的K1芯片全面支持RISC-V Vector 1.0,其VLEN為256,后續(xù)也將推出具有更長VLEN的CPU核,進(jìn)一步強(qiáng)化向量算力。從整個(gè)RISC-V生態(tài)考慮,靈活使用RVV相關(guān)特性,兼容程序在不同向量位寬配置的硬件上運(yùn)行,將更有利于RISC-V向量算力的廣泛應(yīng)用。
目前,社區(qū)在積極投入基于VLA的開發(fā)實(shí)現(xiàn)上,進(jìn)迭時(shí)空也在投入和跟蹤社區(qū)向量化的開發(fā)貢獻(xiàn)工作中。以下是Loop Vectorize優(yōu)化中使能VLA比較關(guān)鍵的幾個(gè)PATCH:
https://github.com/llvm/llvm-project/pull/76172
https://github.com/llvm/llvm-project/pull/93854
https://github.com/llvm/llvm-project/pull/90184
https://github.com/llvm/llvm-project/pull/110412
https://github.com/llvm/llvm-project/pull/108351
目前,自動(dòng)向量化支持還有不少待完善的地方,基于社區(qū)最新分支,進(jìn)迭時(shí)空會(huì)側(cè)重下面的一些工作,且代碼會(huì)陸續(xù)開源貢獻(xiàn)給社區(qū)。
Loop Vectorize 優(yōu)化:Recipe transform to EVLRecipe 的構(gòu)建、逐步移除 Legal Cost Model,完善VPlan-based Cost Model、VPlan-to-VPlan transforms等
RISC-V 后端代價(jià)模型完善
Vector Predicate Lowering到后端的一些通用優(yōu)化
結(jié)語
SpacemiT
進(jìn)迭時(shí)空是一家基于新一代RISC-V架構(gòu)的計(jì)算生態(tài)企業(yè),布局高性能RISC-V CPU核、AI-CPU核、AI CPU芯片、軟件系統(tǒng)等全棧計(jì)算技術(shù),提供端到端的計(jì)算系統(tǒng)解決方案。
RISC-V是一個(gè)開源架構(gòu),其成功離不開繁榮的開源生態(tài),秉承開源理念,我們的一些工作取自開源,也要回饋開源。進(jìn)迭時(shí)空將持續(xù)投入包括編譯器在內(nèi)的RISC-V生態(tài)建設(shè),融入RISC-V的全球發(fā)展,攜手上下游的合作伙伴一起以RISC-V架構(gòu)數(shù)智未來。
-
編譯器
+關(guān)注
關(guān)注
1文章
1659瀏覽量
50044 -
RISC-V
+關(guān)注
關(guān)注
46文章
2525瀏覽量
48495
發(fā)布評論請先 登錄
晶心科技推出突破性的RISC-V 27系列處理器及向量擴(kuò)展指令處理器
CPU優(yōu)化技術(shù)之自動(dòng)向量化實(shí)例
關(guān)于RISC-V學(xué)習(xí)路線圖推薦
科普RISC-V生態(tài)架構(gòu)(認(rèn)識RISC-V)
RISC-V架構(gòu)簡介
安卓支持RISC-V架構(gòu)的技術(shù)剖析
算能重磅發(fā)布行業(yè)首款服務(wù)器級RISC-V CPU算豐SG2042,助力RISC-V邁向高性能計(jì)算
Arm Fortran編譯器開發(fā)人員和參考指南
方舟編譯器官發(fā)布對 RISC-V 后端的支持
CPU優(yōu)化技術(shù)-NEON自動(dòng)向量化
開源硬件系列09期:RISC-V架構(gòu)指令集與編譯器技術(shù)

為什么IAR編譯器對開源ISA:RISC-V業(yè)務(wù)至關(guān)重要?
HighTec C/C++編譯器支持Andes晶心科技RISC-V IP
HighTec C/C++編譯器套件全面支持芯來RISC-V IP

兆松科技發(fā)布高性能RISC-V編譯器ZCC 4.0.0版本

評論