看到Intel最近發(fā)布了QPI直連FPGA的架構(gòu),冬瓜哥回想起幾個(gè)月前寫的一篇文章,現(xiàn)在重新分享給大家。從中你可以了解為何需要FPGA,F(xiàn)PGA是怎么被連接到系統(tǒng)里的,怎么被使用的。
閑話少說,今天我們說一說IBM搞的CAPI,CAPI是OpenPower體系里的一個(gè)技術(shù),其目的是讓FPGA更好更方便的融入現(xiàn)有的系統(tǒng)。那么現(xiàn)有的FPGA是怎么被使用的呢?不如先說說什么是FPGA,要弄清楚什么是FPGA,就得先說說什么是CPU??尚?,CPU大家都知道,冬瓜哥這逼格咋降低了?笑而不語(yǔ)。
·通用CPU是怎么運(yùn)算的?
我們都知道所謂GPCPU(通用目的CPU),也就是什么都能算,但又什么都算不快的CPU,所以其“通用”,比如Intel x86,AMD x86,Power,PowerPC,MIPS,ARM,DragonSon/GodSon(國(guó)產(chǎn))等。而FPGA就是專門為了某種某類計(jì)算而專門優(yōu)化其內(nèi)部的邏輯電路的一種專用CPU。GPCPU內(nèi)部的ALU包含多種運(yùn)算器比如加減乘除以及邏輯(比如xor,and,or,not)運(yùn)算以及整數(shù)和浮點(diǎn)運(yùn)算,我們開始菜單計(jì)算器,算加減法,代碼指令便會(huì)把對(duì)應(yīng)的數(shù)據(jù)導(dǎo)入到CPU的寄存器,CPU收到之后便會(huì)將操作數(shù)輸入到運(yùn)算器的輸入端,并在下一個(gè)時(shí)鐘周期獲取到計(jì)算結(jié)果并輸出到寄存器,然后寫回到主存。當(dāng)然,GPCPU內(nèi)部花費(fèi)了大量的資源(邏輯電路)去做優(yōu)化,包括緩存管理、流水線、多發(fā)射、分支預(yù)測(cè)、亂序執(zhí)行等等,一條指令要最終得到執(zhí)行,都要經(jīng)過這些關(guān)卡的一層層處理,所以,對(duì)于那些遵紀(jì)守法的代碼(比如,順著來沒有任何判斷跳轉(zhuǎn))來講其時(shí)延無疑會(huì)增加,但是目前隨著業(yè)務(wù)越來越復(fù)雜,應(yīng)用程序的判斷條件越來越多,所以這些優(yōu)化會(huì)增加最終性能,雖然時(shí)延相對(duì)上提高了,但是性能絕對(duì)上是增加了,因?yàn)槿绻`判了一個(gè)分支,那么整個(gè)流水線已經(jīng)預(yù)讀入的代碼就會(huì)被沖刷走重新讀入,這個(gè)時(shí)延反而會(huì)更大。
有人問了,我不打開計(jì)算器,就運(yùn)行個(gè)QQ,難道還要算加減法么?如果沒有什么加減乘除運(yùn)算,CPU運(yùn)行QQ到底是運(yùn)行了些什么東西?這問題問得好,問的逼格高,一般人是根本不去想QQ運(yùn)行時(shí)候底層都做了什么的。其實(shí)GPCPU大多時(shí)候還真沒有在算加減乘除,而更多地是做協(xié)調(diào)工作了,也就是把內(nèi)存里某段數(shù)據(jù)讀出來,稍加改動(dòng)或者根本不動(dòng),又寫到內(nèi)存其他地方去。這不閑的么,CPU就干這個(gè)?是的。比如QQ要發(fā)送一句話給某個(gè)好友,其需要調(diào)用TCP協(xié)議棧頂上的soket API,后者就是一段常駐內(nèi)存的OS內(nèi)核代碼,那么QQ.exe如何將這句話傳遞給這段代碼?QQ.exe會(huì)讓CPU把這句話在當(dāng)前內(nèi)存的地址告訴socket API代碼,其會(huì)將這個(gè)地址以及其他參數(shù)寫入到某個(gè)CPU寄存器,對(duì)應(yīng)機(jī)器指令就是“mov 內(nèi)存地址寄存器A”類似這種,然后QQ.exe調(diào)用socket API,對(duì)應(yīng)機(jī)器指令就是“call socket API的內(nèi)存地址”,CPU就會(huì)把QQ.exe當(dāng)前的地址暫存起來以便后續(xù)返回繼續(xù)執(zhí)行(這叫壓棧),然后再跳轉(zhuǎn)到socket API地址來執(zhí)行socket代碼(從內(nèi)存中該地址讀出socket代碼執(zhí)行),socket代碼執(zhí)行之后,會(huì)在CPU寄存器內(nèi)發(fā)現(xiàn)之前傳遞過來的參數(shù)(要發(fā)送數(shù)據(jù)的內(nèi)容等),然后按照這個(gè)參數(shù)向下調(diào)用TCP協(xié)議棧將數(shù)據(jù)打包,分段,貼上IP標(biāo)簽,最后調(diào)用以太網(wǎng)卡驅(qū)動(dòng)程序,調(diào)用過程與上述類似,然后發(fā)送到網(wǎng)卡。這個(gè)過程,在主路徑上,加減乘除運(yùn)算并不是必須的,但是在輔路徑上,比如程序需要記住當(dāng)前發(fā)送了多少內(nèi)容了,TCP協(xié)議棧也要記錄當(dāng)前發(fā)送了多少個(gè)分段了,這些就需要CPU做加法操作,來計(jì)數(shù);另外,在遇到if代碼的時(shí)候,cpu會(huì)比對(duì)多個(gè)輸入條件,對(duì)應(yīng)機(jī)器指令是comp(比較)以及jmpz/jmpnz(遇零跳轉(zhuǎn)/非零跳轉(zhuǎn))等此時(shí)會(huì)用到減法器或者比較器,這恐怕是通用場(chǎng)景下用得最多的ALU運(yùn)算器了。所以,上述這個(gè)過程,根本就不是一個(gè)大運(yùn)算量的過程。但是你如果去聽mp3,解碼RMVB電影,那就需要大運(yùn)算量了,這些場(chǎng)景也是專用場(chǎng)景。
·專用FPGA又是怎么計(jì)算的?
通用CPU做通用場(chǎng)景的代碼執(zhí)行,很強(qiáng),什么都能干,聽著歌聊著QQ做著ppt,再加上個(gè)SSD,體驗(yàn)流暢的感覺。但是讓你算一算分子動(dòng)力學(xué),某個(gè)分子內(nèi)的原子是怎么運(yùn)動(dòng)的?算一算人臉識(shí)別?搞搞搜索?那通用CPU就歇菜了。此時(shí),加減乘除、邏輯、整數(shù)、浮點(diǎn)統(tǒng)統(tǒng)一起上,通用場(chǎng)景下使用比例較少的這些ALU,但是專用場(chǎng)景下,這些ALU反而不夠用了,一個(gè)是數(shù)量太少,一個(gè)是位寬太低。比如XOR運(yùn)算器,如果位寬只有64bit,每個(gè)時(shí)鐘周期只能將兩個(gè)64bit做XOR,如果我要XOR 兩份1GB的數(shù)據(jù),就需要1GB/64bit=?(自己算)個(gè)時(shí)鐘周期,才能算完。此時(shí),專用計(jì)算就派上用場(chǎng)了,也就是所謂的“硬加速”??傮w來講硬加速有4種實(shí)現(xiàn)手段:露點(diǎn)、加寬、并行、直譯。露,就是直接把最終的運(yùn)算單元給露出來,拋掉那些什么分支預(yù)測(cè)等流水線步驟;寬,就是把運(yùn)算器位寬直接加大,一個(gè)周期多算一些數(shù)據(jù);并就是把多種分支直接并行檢測(cè),也就是把比較器/減法器直接并行化,結(jié)果相OR或者AND,來判斷后續(xù)路徑;直譯就是把多種條件直接用譯碼器做出來,一個(gè)周期輸出結(jié)果。所有這些都需要電路層面的改動(dòng),這就產(chǎn)生了FPGA現(xiàn)場(chǎng)可編程門電路陣列。FGPA內(nèi)部就是一堆的直譯表(DRAM,用戶自己寫好邏輯然后輸入進(jìn)去),再加上一些外圍接口,和一些固定的算法器件比如Flash控制器常用的LDPC硬核。NIC、存儲(chǔ)IO卡、防火墻、路由器等,內(nèi)部都使用了應(yīng)加速,比如網(wǎng)卡收到一個(gè)以太網(wǎng)幀,其需要解析幀頭,這種工作如果交給GPCPU的話,那就太慢了,來,先從內(nèi)存讀入代碼看看要讓爺我干點(diǎn)啥?譯完了碼,來,進(jìn)流水線等著吧,我順便去做個(gè)分支預(yù)判,找一找歷史預(yù)判數(shù)據(jù),下一位!進(jìn)了流水線后,親,你先排在后面吧因?yàn)槟阋馁Y源和別人有沖突。最后操作數(shù)到達(dá)ALU,尼瑪,就這么點(diǎn)位寬?小爺這噸位起碼得1Mbit位寬才放得下!親,下次再來吧,來之前先進(jìn)閘刀給你閘成多個(gè)64bit,然后每次算64bit吧。。而硬加速直接把這個(gè)幀載入寄存器,其中電路直接導(dǎo)向各個(gè)譯碼器,直譯出下一步的操作,比如需要比對(duì)ALC,那么就多個(gè)目標(biāo)地址/源地址并行比較一個(gè)周期輸出,這樣才能保證速度。
·專用FPGA怎么與系統(tǒng)對(duì)接?
目前的FPGA都是使用PCIE與host通信的,也就是做成一張PCIE卡查到主板PCIE槽上。主程序通過驅(qū)動(dòng)程序,將需要運(yùn)算的數(shù)據(jù)指針告訴FPGA,然后FPGA從主存DMA讀取待計(jì)算數(shù)據(jù)然后計(jì)算,算完后DMA回主存并通知主程序。
·多核心多CPU系統(tǒng)以及PCIE設(shè)備
所有CPU看到單一物理地址空間,所有Threads看到單一虛擬地址空間,PCIE物理地址空間映射到CPU物理地址空間,CPU物理地址空間也映射到PCIE物理地址空間。
數(shù)據(jù)出了ALU,面對(duì)的一張復(fù)雜的路由網(wǎng)絡(luò),目的地址為內(nèi)存地址,但是其相對(duì)外部網(wǎng)絡(luò)的復(fù)雜性在于,目標(biāo)的位置是不固定的,還可能有多份拷貝。Need Coherency!硬件透明搞定Cache Coherency。CC不負(fù)責(zé)多線程并發(fā)訪問cache line時(shí)的互斥,互斥需要程序顯式發(fā)出lock,底層硬件會(huì)鎖住總線訪問周期。
·PCIE設(shè)備如何與CPU交互?
1.BusDriver將PCIE設(shè)備地址空間映射到CPU物理地址空間并將PCIE地址空間寫入PCIE設(shè)備寄存器。
2.HostDriver讀出PCIE設(shè)備寄存器獲取該設(shè)備對(duì)應(yīng)的PCIE物理地址空間并ioremap()到內(nèi)核虛擬地址空間
3.HostDriver 申請(qǐng)DMA緩存并向PCIE設(shè)備映射的虛擬地址空間寫入控制字、基地址等,這些信息便被寫入設(shè)備寄存器,從而觸發(fā)PCIE設(shè)備根據(jù)基地址從主存DMA拿到需要的指令和數(shù)據(jù)后進(jìn)行處理。
4.PCIE設(shè)備對(duì)主存DMA時(shí),RC自動(dòng)執(zhí)行Probe操作以保證CacheCoherency
·當(dāng)前交互方式存在的不足
1.執(zhí)行路徑長(zhǎng)而且全軟件參與:應(yīng)用call-》傳輸協(xié)議棧(如有)-》Host驅(qū)動(dòng)-》PCIE設(shè)備-》DMAà中斷服務(wù)-》Host驅(qū)動(dòng)-》傳輸協(xié)議棧(如有)-》應(yīng)用buffer
2.PCIE設(shè)備與CPU看到不同的物理地址空間,RC進(jìn)行映射和轉(zhuǎn)換。驅(qū)動(dòng)程序申請(qǐng)內(nèi)存之后得用pci_map_single()映射成PCIE物理地址。
3.用戶態(tài)程序必須主動(dòng)從內(nèi)核地址空間mmap()才可以直接與PCIE設(shè)備DMA互傳數(shù)據(jù)。用戶態(tài)程序必須區(qū)分不同的地址段。
·CAPI1.0版本如何解決當(dāng)前的問題?
AFU—Acceleration Function Unit,主加速邏輯部分,用戶寫入自己設(shè)計(jì)的邏輯和Firmware。
PSL—Power Service Layer, 提供接口給AFU用于讀寫主存和V2P地址翻譯(與CPU側(cè)使用同一個(gè)頁(yè)表,并包含TLB),同時(shí)負(fù)責(zé)Probe CAPP實(shí)現(xiàn)全局cc,并提供Cache。PSL由IBM作為硬核IP提供給FPGA開發(fā)者。
CAPP—Coherent Attached Processor Proxy, 相當(dāng)于FPGA側(cè)的ccAgent,但是被放在了CPU側(cè),其維護(hù)一個(gè)filter目錄并接受來自其他CPU的Probe,未過濾掉的Probe轉(zhuǎn)發(fā)PSL。
·性能能提高多少?
上圖是IBM自己的一個(gè)測(cè)試,利用CAPI enabled FC HBA(基于FGPA),與傳統(tǒng)方式相對(duì)比,性能提升非常大,我沒有是測(cè)過,對(duì)其底層的機(jī)制有點(diǎn)懷疑,F(xiàn)PGA后端同樣使用傳統(tǒng)的FC控制器以及驅(qū)動(dòng)程序連接AFA陣列,這與直接把FC卡插在主機(jī)上相比,增加了一層CAPI,只會(huì)時(shí)延更高,但是結(jié)果卻是時(shí)延下降,由于IBM并沒有提供更多信息,所以這里不好判斷。
評(píng)論
查看更多