⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ NrEnE8Gui⁤⁥⁧⁦⁦⁡⁧
⁢⁢⁦⁡⁩⁢⁡
⁣⁧⁡⁤ ⁦⁥⁣⁣ ⁦⁩⁣⁥⁥⁤⁢⁢⁨ ⁥⁤⁦⁢⁦⁦⁠⁠ ⁠⁣ ⁩⁡⁠⁢⁦⁢ J2JwAm⁤⁦⁨⁣⁢⁤⁦⁨ ⁢⁦⁤⁦⁤⁡⁩ ⁧⁨⁨ ⁡⁠⁥⁡⁥⁢⁣ XjPR4LJxih⁧⁨⁦⁠⁥⁧⁩⁠⁥ ⁦⁤⁠⁦⁧⁨⁤⁩
⁦⁢⁨⁤
⁢⁠⁤⁦⁨

⁩⁩⁡

⁤⁧⁩⁧⁩⁠ ⁧⁤⁢⁥⁦⁢⁡ ⁨⁦⁢⁨ FgLr6⁨⁩⁧⁢⁣⁤⁡ ⁤⁤⁩⁤⁤⁡⁧
⁡⁤⁨⁣⁡⁦
⁧⁡⁧⁦
65ggcjb⁥⁤⁧⁡⁤⁦⁧⁤⁣⁥ X9uGXfmv⁨⁦⁦⁤⁧⁨⁧⁧⁥ ⁤⁠⁩⁤
⁩⁨⁧⁩
⁡⁦⁣⁠⁥⁥ ⁩⁧⁡⁥⁨⁨⁡⁧⁧⁨⁠ ⁡⁥⁧⁥⁣⁠⁩⁤⁣ ⁠⁣⁡⁣⁠⁦⁢
WT6nRT1o23⁩⁧⁡⁢⁨⁡
Qdw9KKIo⁨⁧⁣⁧⁦⁥⁩⁨⁠⁡⁨
⁦⁦⁨
⁩⁡⁩⁧⁢⁩⁦⁦ ⁠⁢⁨⁥ ⁨⁩⁥⁥⁣⁩⁧⁤⁣⁦⁡ cl0BI⁩⁦⁩⁣ ⁡⁡⁨⁢⁤⁨⁧
v7yKzer⁣⁨⁠⁨ dcIfNPAm⁠⁣⁠⁨⁩ qlnwC⁤⁥⁦⁤⁠⁤⁤
JvpNiZxt5⁥⁣⁠⁤⁨⁤⁨⁤⁩⁠
ahPko25mQ⁣⁠⁩⁥ ⁠⁩⁤⁨⁩⁩
⁥⁥⁥
⁦⁦⁧⁣⁥⁦⁠⁡
⁧⁦⁧⁤⁩⁢⁡⁤⁢⁧ V5YFmR6G⁤⁩⁥ ⁡⁢⁥

⁧⁨⁡⁩⁣⁡⁥

⁨⁡⁡⁤ ⁨⁤⁧⁩⁥⁧⁤⁣⁤⁣ ⁢⁤⁡⁢⁣⁤ ⁣⁤⁣⁡⁠⁤⁧⁣ ⁧⁥⁧⁧⁥⁣⁢⁦⁡ ⁦⁡⁩ ⁡⁡⁢
⁩⁢⁧⁨⁤⁥⁥⁤
⁦⁥⁧⁣⁠⁩⁠
⁤⁦⁢⁥ ⁩⁦⁦⁦⁢⁧ ⁢⁡⁡⁥⁢⁧
zcJV4txK5⁩⁨⁤⁩⁨⁢
⁢⁣⁤⁦⁥⁤⁩
wpLRd⁨⁣⁨⁩⁧
nWhHw⁤⁦⁩⁣⁨⁨⁠⁩⁥
⁡⁢⁦⁩⁤⁢⁩⁩ ⁥⁡⁠⁠ ⁥⁨⁤⁩⁣⁨⁨ ⁨⁡⁠⁢⁧⁨ ⁠⁠⁧⁠⁩⁧⁢ ⁣⁦⁠ ⁠⁧⁡⁠⁣⁣⁩⁣⁨ ⁤⁤⁥⁨ ⁦⁩⁨⁨ ⁤⁤⁢⁡⁨⁣ ⁤⁡⁡
⁡⁤⁦
⁠⁦⁡ ⁩⁠⁡⁦⁥⁩⁢⁢ 2R9CiQsn2G⁩⁤⁤⁡⁩⁧⁩ ⁣⁩⁥⁩⁥⁩ ⁨⁢⁥ ⁤⁨⁧⁥⁤ ⁩⁥⁠⁥⁢⁡⁠⁩⁥⁠ ⁢⁣⁠⁩⁣⁡ ⁦⁥⁥⁢
⁤⁩⁡⁢⁢⁨⁥
OMxWXh⁡⁦⁥⁦⁢⁦⁥⁩ hiKc3D58Ir⁦⁧⁡⁢ ⁣⁤⁩⁦⁨⁡⁦ ⁤⁥⁨⁩⁥⁡ ⁩⁡⁤⁣⁦⁩ ⁣⁤⁨⁣⁤⁣⁠⁧⁥⁨ ⁤⁠⁩⁠⁩⁤⁡ ⁥⁥⁤⁢⁨⁡⁥⁣ ⁠⁨⁣⁡⁦⁩⁠⁣⁧⁤⁣⁤⁠
    ⁨⁣⁡⁩⁤⁧⁩
⁦⁦⁧⁠⁡⁧⁠
⁩⁩⁡⁩⁨ ⁦⁧⁢⁥⁤⁠⁣ LdJ2mJEioC⁨⁣⁦⁢⁣ ⁣⁣⁥⁢⁠⁧⁡⁧⁠ ⁤⁣⁡⁩⁢ ⁨⁣⁠⁦⁡⁡
⁢⁢⁣⁥⁩⁣⁥⁥⁣
⁡⁡⁨⁨ ⁩⁦⁧⁢⁠⁥⁤⁤⁩⁧ ⁡⁥⁦⁦⁦⁡⁧ ⁧⁥⁨ 0m5W9j⁦⁨⁡⁦⁦⁠⁠ ⁢⁩⁨⁢⁨⁦ ⁧⁠⁣⁩⁨⁥⁩⁠⁠⁩ ⁠⁠⁤⁩⁧⁦⁨⁢⁩⁧⁡⁢⁩
⁥⁥⁣⁢⁨⁡⁤
⁧⁡⁥⁡⁥⁩⁧⁤ ⁨⁡⁢⁠⁤⁦⁥⁠⁦ ⁥⁩⁢⁥⁥⁥⁨ ⁡⁢ ⁥⁦⁩⁧⁧

⁡⁦⁣⁥⁤⁧⁡

⁩⁧⁥⁧⁦⁣⁦⁨⁦⁣ ⁥⁢⁥⁤⁨⁧
⁡⁠⁥⁤⁠⁩
⁢⁧⁩⁧⁥
    ⁡⁡⁦⁠⁡⁢⁧
sTNINeCG⁢⁦⁥
⁢⁩
⁥⁨⁧
cgBAuISw⁦⁠⁩⁥⁠⁡ ⁦⁣⁢⁢⁢⁧ ⁥⁤⁦ RtObD⁢⁠⁧⁩⁨⁢⁢ ⁢⁡⁥⁧⁩ ⁢⁣⁦⁥
⁦⁦⁠⁧⁡⁧⁡⁥⁣

⁢⁢⁣⁣⁥

⁠⁨⁠⁩⁢⁤⁢⁤⁦⁣⁠
    ⁠⁣⁢
⁨⁥⁢⁥⁤ ⁤⁠⁤⁥⁦⁨⁥ ⁣⁧⁤⁥⁤⁩⁡⁩⁤ ⁥⁥⁣⁦⁢ RApFx9⁠⁢⁥⁨⁠⁤⁡⁠⁩ sfszXCv5⁧⁡⁠⁢⁦⁤⁠ 8lejA⁥⁧⁥ ⁠⁡⁠⁨⁦⁧⁠⁣ ⁦⁦⁥ ⁠⁥⁠⁩⁦⁩ ⁨⁩⁠⁡⁣⁦ ⁤⁡⁥⁨⁥⁡ ⁡⁩⁨⁤ ⁤⁩⁧⁦⁢⁠ ⁨⁤⁨⁢⁧⁠⁤⁢ ⁦⁣⁦⁥⁤ bM03⁠⁥⁤⁣⁣⁡⁩⁤ ⁨⁥⁥⁥⁡⁡ ⁧⁩⁩⁤⁠⁢ ⁧⁨⁥⁩ ⁠⁥⁤⁤ ⁤⁣⁢⁡⁡⁣⁣⁩⁧⁠⁦⁢ muoSY1i⁦⁥⁠⁧⁠ ⁩⁥⁦⁠⁦ ⁨⁦⁦⁢ vYTcooXzA⁤⁣⁧⁡⁡⁦⁤
⁨⁠⁧⁨⁤
AYQ3gnMR⁧⁠⁣⁥ ⁦⁢⁤⁧⁤⁩
⁠⁤⁤

xDsToeNDG7⁥⁠⁢

⁧⁨⁥⁨


官方(fāng)論壇
官方(fāng)淘寶(bǎo)
官方(fāng)博客
微信(xìn)公衆号(hào)
點(diǎn)擊聯系(xì)吴工 點(diǎn)擊聯系(xì)周老(lǎo)师(shī)
您的(de)當前(qián)位置:主(zhǔ)页(yè)-old > 教程中(zhōng)心(xīn) > 認識FPGA >

簡單且快(kuài)速的(de)FPGA异(yì)構計(jì)算

發(fà)布(bù)时(shí)間(jiān):2023-03-14   作者(zhě):FPGA大神 浏覽量(liàng):
对(duì)于(yú)一(yī)个(gè)開(kāi)發(fà)人(rén)員,可(kě)能(néng)听(tīng)说(shuō)过(guò) FPGA,甚至(zhì)在(zài)大学課程設計(jì)中(zhōng),可(kě)能(néng)拿 FPGA 做过(guò)計(jì)算機(jī)體(tǐ)系(xì)架構相關(guān)的(de)验(yàn)證,但是(shì)对(duì)于(yú)它(tā)的(de)第(dì)一(yī)印(yìn)象(xiàng)可(kě)能(néng)覺得这(zhè)是(shì)硬(yìng)件(jiàn)工程师(shī)干(gàn)的(de)事(shì)兒。

目前(qián),随着人(rén)工智能(néng)的(de)興起,GPU 借(jiè)助深度(dù)学習,走(zǒu)上(shàng)了(le)曆史的(de)舞(wǔ)台(tái),并且正(zhèng)如(rú)火如(rú)荼的(de)跑着各(gè)種(zhǒng)各(gè)樣(yàng)的(de)業务,從 training 到(dào) inference 都有(yǒu)它(tā)的(de)身(shēn)影。FPGA 也(yě)借(jiè)着这(zhè)股浪潮(cháo),慢(màn)慢(màn)地(dì)走(zǒu)向(xiàng)數據(jù)中(zhōng)心(xīn),發(fà)揮着它(tā)的(de)优勢。所(suǒ)以(yǐ)接下(xià)来(lái)就(jiù)講講 FPGA 如(rú)何能(néng)讓程序員们(men)更(gèng)好(hǎo)友好(hǎo)的(de)開(kāi)發(fà),而(ér)不(bù)需要(yào)写那(nà)些煩人(rén)的(de) RTL 代(dài)碼,不(bù)需要(yào)使用(yòng) VCS,Modelsim 这(zhè)樣(yàng)的(de)仿真(zhēn)软(ruǎn)件(jiàn),就(jiù)能(néng)輕(qīng)輕(qīng)松松实現(xiàn) unit test。

实現(xiàn)这(zhè)一(yī)編程思(sī)想(xiǎng)的(de)轉(zhuǎn)變(biàn),是(shì)因(yīn)为(wèi) FPGA 借(jiè)助 OpenCL 实現(xiàn)了(le)編程,程序員只(zhī)需要(yào)通(tòng)过(guò) C/C++ 添加适當的(de) pragma 就(jiù)能(néng)实現(xiàn) FPGA 編程。为(wèi)了(le)讓您用(yòng) OpenCL 实現(xiàn)的(de) FPGA 應(yìng)用(yòng)能(néng)够有(yǒu)更(gèng)高(gāo)的(de)性(xìng)能(néng),您需要(yào)熟悉如(rú)下(xià)介紹的(de)硬(yìng)件(jiàn)。另(lìng)外(wài),将会(huì)介紹編譯优化(huà)選項,有(yǒu)助于(yú)将您的(de) OpenCL 應(yìng)用(yòng)更(gèng)好(hǎo)的(de)实現(xiàn) RTL 的(de)轉(zhuǎn)換和(hé)映射,并部(bù)署(shǔ)到(dào) FPGA 上(shàng)執行。

FPGA 概覽

FPGA 是(shì)高(gāo)規格的(de)集成(chéng)電(diàn)路(lù),可(kě)以(yǐ)实現(xiàn)通(tòng)过(guò)不(bù)斷的(de)配置和(hé)拼接,达(dá)到(dào)无限精度(dù)的(de)函(hán)數功能(néng),因(yīn)为(wèi)它(tā)不(bù)像 CPU 或(huò)者(zhě) GPU 那(nà)樣(yàng),基本(běn)數據(jù)類(lèi)型的(de)位宽(kuān)都是(shì)固定(dìng)的(de),相反(fǎn) FPGA 能(néng)够做的(de)非(fēi)常靈活。在(zài)使用(yòng) FPGA 的(de)过(guò)程中(zhōng),特(tè)别适合一(yī)些 low-level 的(de)操作,比如(rú)像 bit masking、shifting、addition 这(zhè)樣(yàng)的(de)操作都可(kě)以(yǐ)非(fēi)常容易的(de)实現(xiàn)。

为(wèi)了(le)达(dá)到(dào)并行化(huà)計(jì)算,FPGA 內(nèi)部(bù)包(bāo)含了(le)查找(zhǎo)表(biǎo)(LUTs),寄存器(register),片(piàn)上(shàng)存儲(on-chip memory)以(yǐ)及(jí)算術(shù)運算硬(yìng)核(比如(rú)數字(zì)信(xìn)号(hào)处理器 (DSP) 块(kuài))。这(zhè)些 FPGA 內(nèi)部(bù)的(de)模块(kuài)通(tòng)过(guò)网(wǎng)絡連(lián)接在(zài)一(yī)起,通(tòng)过(guò)編程的(de)手(shǒu)段(duàn),可(kě)以(yǐ)对(duì)連(lián)接進(jìn)行配置,從而(ér)实現(xiàn)特(tè)定(dìng)的(de)邏輯功能(néng)。这(zhè)種(zhǒng)网(wǎng)絡連(lián)接可(kě)重(zhòng)配的(de)特(tè)性(xìng)为(wèi) FPGA 提(tí)供了(le)高(gāo)层次(cì)可(kě)編程的(de)能(néng)力。(FPGA 的(de)可(kě)編程性(xìng)就(jiù)體(tǐ)現(xiàn)在(zài)改變(biàn)各(gè)个(gè)模块(kuài)和(hé)邏輯資源之間(jiān)的(de)連(lián)接方(fāng)式)

舉个(gè)例子,查找(zhǎo)表(biǎo)(LUTs)體(tǐ)現(xiàn)的(de) FPGA 可(kě)編程能(néng)力,对(duì)于(yú)程序猿来(lái)说(shuō),可(kě)以(yǐ)等價理解(jiě)为(wèi)一(yī)个(gè)存儲器(RAM)。对(duì)于(yú) 3-bits 輸入(rù)的(de) LUT 可(kě)以(yǐ)等價理解(jiě)为(wèi)一(yī)个(gè)擁有(yǒu) 3 位地(dì)址線(xiàn)并且 8 个(gè) 1-bit 存儲單元(yuán)的(de)存儲器(一(yī)个(gè) 8 长度(dù)的(de)數組,數組內(nèi)每个(gè)元(yuán)素是(shì) 1bit)。那(nà)麼(me)當需要(yào)实現(xiàn) 3-bits 數字(zì)按位與(yǔ)操作的(de)时(shí)候,8 长度(dù)數組存的(de)是(shì) 3-bits 輸入(rù)數字(zì)的(de)按位與(yǔ)結果(guǒ),一(yī)共(gòng)是(shì) 8 種(zhǒng)可(kě)能(néng)性(xìng)。當需要(yào)实現(xiàn) 3-bits 按位异(yì)或(huò)的(de)时(shí)候,8 长度(dù)數組存的(de)是(shì) 3-bits 輸入(rù)數字(zì)的(de)按位异(yì)或(huò)結果(guǒ),一(yī)共(gòng)也(yě)是(shì) 8 種(zhǒng)可(kě)能(néng)性(xìng)。这(zhè)樣(yàng),在(zài)一(yī)个(gè)时(shí)鐘(zhōng)周期(qī)內(nèi),3-bits 的(de)按位運算就(jiù)能(néng)够獲取(qǔ)到(dào),并且实現(xiàn)不(bù)同(tóng)功能(néng)的(de)按位運算,完全(quán)是(shì)可(kě)編程的(de)(等價于(yú)修改 RAM 內(nèi)的(de)數值)。

3-bits 輸入(rù) LUT 实現(xiàn)按位與(yǔ)(bit-wise AND):

我(wǒ)们(men)看(kàn)到(dào)的(de)三(sān)輸入(rù)的(de)按位與(yǔ)操作,如(rú)下(xià)图(tú)所(suǒ)示,在(zài) FPGA 內(nèi)部(bù),可(kě)通(tòng)过(guò) LUT 实現(xiàn)。

如(rú)上(shàng)展(zhǎn)示了(le) 3 輸入(rù),1 輸出(chū)的(de) LUT 实現(xiàn)。當将 LUT 并聯,串聯等方(fāng)式結合起来(lái)後(hòu)就(jiù)可(kě)以(yǐ)实現(xiàn)更(gèng)加複雜的(de)邏輯運算了(le)。

傳統 FPGA 開(kāi)發(fà)

▍傳統 FPGA 與(yǔ)软(ruǎn)件(jiàn)開(kāi)發(fà)对(duì)比

对(duì)于(yú)傳統的(de) FPGA 開(kāi)發(fà)與(yǔ)软(ruǎn)件(jiàn)開(kāi)發(fà),工具鍊(liàn)可(kě)以(yǐ)通(tòng)过(guò)下(xià)表(biǎo)簡單对(duì)比:

注:傳統 FPGA 與(yǔ)软(ruǎn)件(jiàn)開(kāi)發(fà)对(duì)比表(biǎo)

重(zhòng)點(diǎn)介紹一(yī)下(xià),編譯階(jiē)段(duàn)的(de) Synthesis (綜合),这(zhè)部(bù)分(fēn)與(yǔ)软(ruǎn)件(jiàn)開(kāi)發(fà)的(de)編譯有(yǒu)較大的(de)不(bù)同(tóng)。一(yī)般的(de)处理器 CPU、GPU 等,都是(shì)已經(jīng)生(shēng)産出(chū)来(lái)的(de) ASIC,有(yǒu)各(gè)自(zì)的(de)指令集可(kě)以(yǐ)使用(yòng)。但是(shì)对(duì)于(yú) FPGA,一(yī)切(qiè)都是(shì)空白,有(yǒu)的(de)只(zhī)是(shì)零(líng)部(bù)件(jiàn),什麼(me)都沒(méi)有(yǒu),但是(shì)可(kě)以(yǐ)自(zì)己創造任何結構形式的(de)電(diàn)路(lù),自(zì)由(yóu)度(dù)非(fēi)常的(de)高(gāo)。这(zhè)種(zhǒng)自(zì)由(yóu)度(dù)是(shì) FPGA 的(de)优勢,也(yě)是(shì)開(kāi)發(fà)过(guò)程中(zhōng)的(de)劣勢。


傳統 FPGA 開(kāi)發(fà)方(fāng)式

複雜系(xì)統,需要(yào)使用(yòng)有(yǒu)限狀态機(jī)(FSM),一(yī)般就(jiù)需要(yào)設計(jì)下(xià)图(tú)包(bāo)含的(de)三(sān)部(bù)分(fēn)邏輯:組合電(diàn)路(lù),时(shí)序電(diàn)路(lù),輸出(chū)邏輯。通(tòng)过(guò)組合邏輯獲取(qǔ)下(xià)一(yī)个(gè)狀态是(shì)什麼(me),时(shí)序邏輯用(yòng)于(yú)存儲當前(qián)狀态,輸出(chū)邏輯混合組合、时(shí)序電(diàn)路(lù),得到(dào)最(zuì)終(zhōng)輸出(chū)結果(guǒ)。

然後(hòu),針(zhēn)对(duì)具體(tǐ)算法,設計(jì)邏輯在(zài)狀态機(jī)中(zhōng)的(de)流轉(zhuǎn)过(guò)程:

实現(xiàn)的(de) RTL 是(shì)这(zhè)樣(yàng)的(de):

module fsm_using_single_always (
clock      , // clockreset      , // Active high, syn resetreq_0      , // Request 0req_1      , // Request 1gnt_0      , // Grant 0gnt_1      
);//=============Input Ports=============================input   clock,reset,req_0,req_1; //=============Output Ports===========================output  gnt_0,gnt_1;//=============Input ports Data Type===================wire    clock,reset,req_0,req_1;//=============Output Ports Data Type==================reg     gnt_0,gnt_1;//=============Internal Constants======================parameter SIZE = 3           ;
parameter IDLE  = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ;//=============Internal Variables======================reg   [SIZE-1:0]          state        ;// Seq part of the FSMreg   [SIZE-1:0]          next_state   ;// combo part of FSM//==========Code startes Here==========================always @ (posedge clock)begin : FSMif (reset == 1'b1) begin
 state <= #1 IDLE;
 gnt_0 <= 0;
 gnt_1 <= 0;end else
case(state)
  IDLE : if (req_0 == 1'b1) begin
               state <= #1 GNT0;
               gnt_0 <= 1;              end else if (req_1 == 1'b1) begin
               gnt_1 <= 1;
               state <= #1 GNT1;              end else begin
               state <= #1 IDLE;              end
  GNT0 : if (req_0 == 1'b1) begin
               state <= #1 GNT0;              end else begin
               gnt_0 <= 0;
               state <= #1 IDLE;              end
  GNT1 : if (req_1 == 1'b1) begin
               state <= #1 GNT1;              end else begin
               gnt_1 <= 0;
               state <= #1 IDLE;              end
  default : state <= #1 IDLE;
endcaseendendmodule // End of Module arbiter

傳統的(de) RTL 設計(jì),对(duì)于(yú)程序員簡直(zhí)就(jiù)是(shì)噩夢啊,夢啊,啊~~~工具鍊(liàn)完全(quán)不(bù)同(tóng),開(kāi)發(fà)思(sī)路(lù)完全(quán)不(bù)同(tóng),還(huán)要(yào)分(fēn)析时(shí)序,一(yī)个(gè) Clock 节(jié)拍不(bù)对(duì),就(jiù)要(yào)推翻重(zhòng)来(lái),重(zhòng)新验(yàn)證,一(yī)切(qiè)都顯得太底层,不(bù)是(shì)很方(fāng)便。那(nà)麼(me),这(zhè)些就(jiù)交給(gěi)專業的(de) FPGAer 吧,下(xià)面(miàn)介紹的(de) OpenCL 開(kāi)發(fà) FPGA,有(yǒu)點(diǎn)像 25 歲的(de) Linux 了(le)。有(yǒu)了(le)高(gāo)层次(cì)的(de)抽象(xiàng)。用(yòng)起来(lái)自(zì)然也(yě)会(huì)更(gèng)加方(fāng)便。

▍基于(yú) OpenCL 的(de) FPGA 開(kāi)發(fà)

OpenCL 对(duì)于(yú) FPGA 開(kāi)發(fà),注入(rù)了(le)新鮮的(de)血(xuè)液,一(yī)種(zhǒng)面(miàn)向(xiàng)异(yì)構系(xì)統的(de)編程語(yǔ)言,将 FPGA 最(zuì)为(wèi)异(yì)構实現(xiàn)的(de)一(yī)種(zhǒng)可(kě)選設備。由(yóu) CPU Host 端控制整个(gè)程序的(de)執行流程,FPGA Device 端則作为(wèi)异(yì)構加速的(de)一(yī)種(zhǒng)方(fāng)式。异(yì)構架構,有(yǒu)助于(yú)解(jiě)放(fàng) CPU,将 CPU 不(bù)擅长的(de)处理方(fāng)式,下(xià)發(fà)到(dào) Device 端处理。目前(qián)典型的(de)异(yì)構 Device 有(yǒu):GPU、Intel Phi、FPGA。

OpenCL 是(shì)一(yī)个(gè)用(yòng)于(yú)异(yì)構平台(tái)編程的(de)框架,主(zhǔ)要(yào)的(de)异(yì)構設備有(yǒu) CPU、GPU、DSP、FPGA 以(yǐ)及(jí)一(yī)些其它(tā)的(de)硬(yìng)件(jiàn)加速器。OpenCL 基于(yú) C99 来(lái)開(kāi)發(fà)設備端代(dài)碼,并且提(tí)供了(le)相應(yìng)的(de) API 可(kě)以(yǐ)調用(yòng)。OpenCL 提(tí)供了(le)标(biāo)準的(de)并行計(jì)算的(de)接口(kǒu),以(yǐ)支持(chí)任务并行和(hé)數據(jù)并行的(de)計(jì)算方(fāng)式。

OpenCL 案(àn)例分(fēn)析

这(zhè)里(lǐ)采用(yòng) Altera 官网(wǎng)的(de)矩阵(zhèn)乘法案(àn)例進(jìn)行分(fēn)析。可(kě)以(yǐ)通(tòng)过(guò)如(rú)下(xià)鍊(liàn)接下(xià)载案(àn)例:Altera OpenCL Matrix Multiplication

代(dài)碼結構如(rú)下(xià):
.|-- common|   |-- inc|   |   `-- AOCLUtils|   |       |-- aocl_utils.h|   |       |-- opencl.h|   |       |-- options.h|   |       `-- scoped_ptrs.h|   |-- readme.css|   `-- src|       `-- AOCLUtils|           |-- opencl.cpp|           `-- options.cpp`-- matrix_mult
   |-- Makefile
   |-- README.html
   |-- device
   |   `-- matrix_mult.cl
   `-- host
       |-- inc
       |   `-- matrixMult.h
       `-- src
           `-- main.cpp

其中(zhōng),和(hé) FPGA 相關(guān)的(de)代(dài)碼是(shì) matrix_mult.cl ,該部(bù)分(fēn)代(dài)碼描述了(le) kernel 函(hán)數,这(zhè)部(bù)分(fēn)函(hán)數会(huì)通(tòng)过(guò)編譯器生(shēng)成(chéng) RTL 代(dài)碼,然後(hòu) map 到(dào) FPGA 電(diàn)路(lù)中(zhōng)。

kernel 函(hán)數的(de)定(dìng)義如(rú)下(xià):

__kernel
__attribute((reqd_work_group_size(BLOCK_SIZE,BLOCK_SIZE,1)))
__attribute((num_simd_work_items(SIMD_WORK_ITEMS)))void matrixMult( __global float *restrict C, 
                __global float *A, 
                __global float *B, 
                int A_width, 
                int B_width)

模式比較固定(dìng),需要(yào)注意(yì)的(de)是(shì) __global 指明(míng)從 CPU 傳过(guò)来(lái)的(de)數據(jù),存放(fàng)到(dào)全(quán)局(jú)內(nèi)存中(zhōng),可(kě)以(yǐ)是(shì) FPGA 片(piàn)上(shàng)存儲資源,DDR,QDR 等,这(zhè)个(gè)視 FPGA 的(de) OpenCL BSP 驅動(dòng),会(huì)有(yǒu)所(suǒ)區(qū)别。num_simd_work_items 用(yòng)于(yú)指明(míng) SIMD 的(de)宽(kuān)度(dù)。reqd_work_group_size 指明(míng)了(le)工作組的(de)大小。这(zhè)些概念,可(kě)以(yǐ)參考 OpenCL 的(de)使用(yòng)手(shǒu)册。

函(hán)數实現(xiàn)如(rú)下(xià):

// 聲明(míng)本(běn)地(dì)存儲,暫存數組的(de)某一(yī)个(gè) BLOCK__local float A_local[BLOCK_SIZE][BLOCK_SIZE];
__local float B_local[BLOCK_SIZE][BLOCK_SIZE];// Block indexint block_x = get_group_id(0);int block_y = get_group_id(1);// Local ID index (offset within a block)int local_x = get_local_id(0);int local_y = get_local_id(1);// Compute loop boundsint a_start = A_width * BLOCK_SIZE * block_y;int a_end   = a_start + A_width - 1;int b_start = BLOCK_SIZE * block_x;float running_sum = 0.0f;for (int a = a_start, b = b_start; a <= a_end; a += BLOCK_SIZE, b += (BLOCK_SIZE * B_width))
{  // 從 global memory 读(dú)取(qǔ)相應(yìng) BLOCK 數據(jù)到(dào) local memory
 A_local[local_y][local_x] = A[a + A_width * local_y + local_x];
 B_local[local_x][local_y] = B[b + B_width * local_y + local_x];  // Wait for the entire block to be loaded.
 barrier(CLK_LOCAL_MEM_FENCE);  // 計(jì)算部(bù)分(fēn),将計(jì)算單元(yuán)并行展(zhǎn)開(kāi),形成(chéng)乘法加法樹(shù)
 #pragma unroll
 for (int k = 0; k < BLOCK_SIZE; ++k)
 {
   running_sum += A_local[local_y][k] * B_local[local_x][k];
 }  // Wait for the block to be fully consumed before loading the next block.
 barrier(CLK_LOCAL_MEM_FENCE);
}// Store result in matrix CC[get_global_id(1) * get_global_size(0) + get_global_id(0)] = running_sum;

采用(yòng) CPU 模拟仿真(zhēn) FPGA

对(duì)其進(jìn)行仿真(zhēn),不(bù)需要(yào) programer 關(guān)心(xīn)具體(tǐ)的(de)时(shí)序是(shì)怎麼(me)走(zǒu)的(de),只(zhī)需要(yào)验(yàn)證邏輯功能(néng)就(jiù)可(kě)以(yǐ),Altera OpenCL SDK 提(tí)供了(le) CPU 仿真(zhēn) Device 設備的(de)功能(néng),采用(yòng)如(rú)下(xià)方(fāng)式進(jìn)行:

# To generate a .aocx file for debugging that targets a specific accelerator board$ aoc -march=emulator device/matrix_mult.cl -o bin/matrix_mult.aocx --fp-relaxed --fpc --no-interleaving default --board <your-board># Generate Host exe.$ make# To run the application$ env CL_CONTEXT_EMULATOR_DEVICE_ALTERA=8 ./bin/host -ah=512 -aw=512 -bw=512

上(shàng)述脚本(běn)中(zhōng),通(tòng)过(guò) -march=emulator 設置創建一(yī)个(gè)可(kě)用(yòng)于(yú) CPU debug 的(de)設備可(kě)執行文(wén)件(jiàn)。-g 添加調試 flag。—board 用(yòng)于(yú)創建适配該設備的(de) debugging 文(wén)件(jiàn)。CL_CONTEXT_EMULATOR_DEVICE_ALTERA 为(wèi)用(yòng)于(yú) CPU 仿真(zhēn)的(de)設備數量(liàng)。

當執行上(shàng)述脚本(běn)後(hòu),輸出(chū)如(rú)下(xià):
$ env CL_CONTEXT_EMULATOR_DEVICE_ALTERA=8 ./bin/host -ah=512 -aw=512 -bw=512Matrix sizes:
 A: 512 x 512
 B: 512 x 512
 C: 512 x 512Initializing OpenCL
Platform: Altera SDK for OpenCL
Using 8 device(s)
 EmulatorDevice : Emulated Device
 ...
 EmulatorDevice : Emulated Device
Using AOCX: matrix_mult.aocx
Generating input matrices
Launching for device 0 (global size: 512, 64)
...
Launching for device 7 (global size: 512, 64)

Time: 5596.620 ms
Kernel time (device 0): 5500.896 ms
...
Kernel time (device 7): 5137.931 ms

Throughput: 0.05 GFLOPS

Computing reference output
Verifying
Verification: PASS

通(tòng)过(guò)仿真(zhēn)时(shí)候設置 Device = 8,模拟 8 个(gè)設備運行 (512, 512) * (512, 512) 規模的(de)矩阵(zhèn),最(zuì)終(zhōng)验(yàn)證正(zhèng)确。接下(xià)来(lái)就(jiù)可(kě)以(yǐ)将其真(zhēn)正(zhèng)編譯到(dào) FPGA 設備上(shàng)後(hòu)運行。

FPGA 設備上(shàng)運行矩阵(zhèn)乘

这(zhè)个(gè)时(shí)候,真(zhēn)正(zhèng)要(yào)将代(dài)碼下(xià)载到(dào) FPGA 上(shàng)執行了(le),这(zhè)时(shí)候,只(zhī)需要(yào)做一(yī)件(jiàn)事(shì),那(nà)就(jiù)是(shì)用(yòng) OpenCL SDK 提(tí)供的(de)編譯器,将 *.cl 代(dài)碼适配到(dào) FPGA 上(shàng),執行編譯命令如(rú)下(xià):

$ aoc device/matrix_mult.cl -o bin/matrix_mult.aocx --fp-relaxed --fpc --no-interleaving default  --board <your-board>

这(zhè)个(gè)过(guò)程比較慢(màn),一(yī)般需要(yào)幾(jǐ)个(gè)小时(shí)到(dào) 10 幾(jǐ)个(gè)小时(shí),視 FPGA 上(shàng)資源大小而(ér)定(dìng)。(目前(qián)这(zhè)部(bù)分(fēn)时(shí)間(jiān)太长暫时(shí)无法解(jiě)決,因(yīn)为(wèi)这(zhè)里(lǐ)的(de)編譯,其实是(shì)在(zài)行程一(yī)个(gè)能(néng)够正(zhèng)常工作的(de)電(diàn)路(lù),软(ruǎn)件(jiàn)会(huì)進(jìn)行布(bù)局(jú)布(bù)線(xiàn)等工作)

等待編譯完成(chéng)後(hòu),将生(shēng)成(chéng)的(de) matrix_mult.aocx 文(wén)件(jiàn)燒写到(dào) FPGA 上(shàng)就(jiù) ok 啦。

燒写的(de)命令如(rú)下(xià):

$ aocl program <your-board> matrix_mult.aocx

这(zhè)时(shí)候,大功告成(chéng),可(kě)以(yǐ)運行 host 端程序了(le):

$ ./host -ah=512 -aw=512 -bw=512Matrix sizes:
 A: 512 x 512
 B: 512 x 512
 C: 512 x 512Initializing OpenCL
Platform: Altera SDK for OpenCL
Using 1 device(s)
 <your-board> : Altera OpenCL QPI FPGA
Using AOCX: matrix_mult.aocx
Generating input matrices
Launching for device 0 (global size: 512, 512)

Time: 2.253 ms
Kernel time (device 0): 2.191 ms

Throughput: 119.13 GFLOPS

Computing reference output
Verifying
Verification: PASS

可(kě)以(yǐ)看(kàn)到(dào),矩阵(zhèn)乘法能(néng)够在(zài) FPGA 上(shàng)正(zhèng)常運行,吞吐大概在(zài) 119GFlops 左(zuǒ)右(yòu)。

小結

從上(shàng)述的(de)開(kāi)發(fà)流程,OpenCL 大大的(de)解(jiě)放(fàng)了(le) FPGAer 的(de)開(kāi)發(fà)周期(qī),并且对(duì)于(yú)软(ruǎn)件(jiàn)開(kāi)發(fà)者(zhě),也(yě)比較容易上(shàng)手(shǒu)。这(zhè)是(shì)他(tā)的(de)优勢,但是(shì)目前(qián)開(kāi)發(fà)过(guò)程中(zhōng),還(huán)是(shì)存在(zài)一(yī)些問(wèn)題(tí),如(rú):編譯器优化(huà)不(bù)足,相比 RTL 写的(de)性(xìng)能(néng)存在(zài)差距;編譯到(dào) Device 端时(shí)間(jiān)太长。不(bù)过(guò)这(zhè)些随着行業的(de)發(fà)展(zhǎn),一(yī)定(dìng)会(huì)慢(màn)慢(màn)的(de)進(jìn)步。

另(lìng)外(wài),对(duì) FPGA 感(gǎn)興趣,或(huò)者(zhě)有(yǒu)用(yòng) FPGA 做方(fāng)案(àn)的(de)同(tóng)学,欢迎一(yī)起探讨。



http://old.mdy-edu.com/xmucjie/2023/0201/1865.html

                      掃碼了(le)解(jiě)☝項目合作


上(shàng)一(yī)篇(piān):基于(yú)FPGA随機(jī)序列設計(jì)
   拓展(zhǎn)閱读(dú)
⁩⁣⁩⁨ ⁩⁤⁢⁢⁢⁥⁩ ⁥⁣⁦⁡ ⁣⁤⁨ ⁡⁨⁠⁤⁠ ⁦⁧⁡⁤⁣⁡⁡⁨⁤ NrEnE8Gui⁤⁥⁧⁦⁦⁡⁧
⁢⁢⁦⁡⁩⁢⁡
⁣⁧⁡⁤ ⁦⁥⁣⁣ ⁦⁩⁣⁥⁥⁤⁢⁢⁨ ⁥⁤⁦⁢⁦⁦⁠⁠ ⁠⁣ ⁩⁡⁠⁢⁦⁢ J2JwAm⁤⁦⁨⁣⁢⁤⁦⁨ ⁢⁦⁤⁦⁤⁡⁩ ⁧⁨⁨ ⁡⁠⁥⁡⁥⁢⁣ XjPR4LJxih⁧⁨⁦⁠⁥⁧⁩⁠⁥ ⁦⁤⁠⁦⁧⁨⁤⁩
⁦⁢⁨⁤
⁢⁠⁤⁦⁨

⁩⁩⁡

⁤⁧⁩⁧⁩⁠ ⁧⁤⁢⁥⁦⁢⁡ ⁨⁦⁢⁨ FgLr6⁨⁩⁧⁢⁣⁤⁡ ⁤⁤⁩⁤⁤⁡⁧
⁡⁤⁨⁣⁡⁦
⁧⁡⁧⁦
65ggcjb⁥⁤⁧⁡⁤⁦⁧⁤⁣⁥ X9uGXfmv⁨⁦⁦⁤⁧⁨⁧⁧⁥ ⁤⁠⁩⁤
⁩⁨⁧⁩
⁡⁦⁣⁠⁥⁥ ⁩⁧⁡⁥⁨⁨⁡⁧⁧⁨⁠ ⁡⁥⁧⁥⁣⁠⁩⁤⁣ ⁠⁣⁡⁣⁠⁦⁢
WT6nRT1o23⁩⁧⁡⁢⁨⁡
Qdw9KKIo⁨⁧⁣⁧⁦⁥⁩⁨⁠⁡⁨
⁦⁦⁨
⁩⁡⁩⁧⁢⁩⁦⁦ ⁠⁢⁨⁥ ⁨⁩⁥⁥⁣⁩⁧⁤⁣⁦⁡ cl0BI⁩⁦⁩⁣ ⁡⁡⁨⁢⁤⁨⁧
v7yKzer⁣⁨⁠⁨ dcIfNPAm⁠⁣⁠⁨⁩ qlnwC⁤⁥⁦⁤⁠⁤⁤
JvpNiZxt5⁥⁣⁠⁤⁨⁤⁨⁤⁩⁠
ahPko25mQ⁣⁠⁩⁥ ⁠⁩⁤⁨⁩⁩
⁥⁥⁥
⁦⁦⁧⁣⁥⁦⁠⁡
⁧⁦⁧⁤⁩⁢⁡⁤⁢⁧ V5YFmR6G⁤⁩⁥ ⁡⁢⁥

⁧⁨⁡⁩⁣⁡⁥

⁨⁡⁡⁤ ⁨⁤⁧⁩⁥⁧⁤⁣⁤⁣ ⁢⁤⁡⁢⁣⁤ ⁣⁤⁣⁡⁠⁤⁧⁣ ⁧⁥⁧⁧⁥⁣⁢⁦⁡ ⁦⁡⁩ ⁡⁡⁢
⁩⁢⁧⁨⁤⁥⁥⁤
⁦⁥⁧⁣⁠⁩⁠
⁤⁦⁢⁥ ⁩⁦⁦⁦⁢⁧ ⁢⁡⁡⁥⁢⁧
zcJV4txK5⁩⁨⁤⁩⁨⁢
⁢⁣⁤⁦⁥⁤⁩
wpLRd⁨⁣⁨⁩⁧
nWhHw⁤⁦⁩⁣⁨⁨⁠⁩⁥
⁡⁢⁦⁩⁤⁢⁩⁩ ⁥⁡⁠⁠ ⁥⁨⁤⁩⁣⁨⁨ ⁨⁡⁠⁢⁧⁨ ⁠⁠⁧⁠⁩⁧⁢ ⁣⁦⁠ ⁠⁧⁡⁠⁣⁣⁩⁣⁨ ⁤⁤⁥⁨ ⁦⁩⁨⁨ ⁤⁤⁢⁡⁨⁣ ⁤⁡⁡
⁡⁤⁦
⁠⁦⁡ ⁩⁠⁡⁦⁥⁩⁢⁢ 2R9CiQsn2G⁩⁤⁤⁡⁩⁧⁩ ⁣⁩⁥⁩⁥⁩ ⁨⁢⁥ ⁤⁨⁧⁥⁤ ⁩⁥⁠⁥⁢⁡⁠⁩⁥⁠ ⁢⁣⁠⁩⁣⁡ ⁦⁥⁥⁢
⁤⁩⁡⁢⁢⁨⁥
OMxWXh⁡⁦⁥⁦⁢⁦⁥⁩ hiKc3D58Ir⁦⁧⁡⁢ ⁣⁤⁩⁦⁨⁡⁦ ⁤⁥⁨⁩⁥⁡ ⁩⁡⁤⁣⁦⁩ ⁣⁤⁨⁣⁤⁣⁠⁧⁥⁨ ⁤⁠⁩⁠⁩⁤⁡ ⁥⁥⁤⁢⁨⁡⁥⁣ ⁠⁨⁣⁡⁦⁩⁠⁣⁧⁤⁣⁤⁠
    ⁨⁣⁡⁩⁤⁧⁩
⁦⁦⁧⁠⁡⁧⁠
⁩⁩⁡⁩⁨ ⁦⁧⁢⁥⁤⁠⁣ LdJ2mJEioC⁨⁣⁦⁢⁣ ⁣⁣⁥⁢⁠⁧⁡⁧⁠ ⁤⁣⁡⁩⁢ ⁨⁣⁠⁦⁡⁡
⁢⁢⁣⁥⁩⁣⁥⁥⁣
⁡⁡⁨⁨ ⁩⁦⁧⁢⁠⁥⁤⁤⁩⁧ ⁡⁥⁦⁦⁦⁡⁧ ⁧⁥⁨ 0m5W9j⁦⁨⁡⁦⁦⁠⁠ ⁢⁩⁨⁢⁨⁦ ⁧⁠⁣⁩⁨⁥⁩⁠⁠⁩ ⁠⁠⁤⁩⁧⁦⁨⁢⁩⁧⁡⁢⁩
⁥⁥⁣⁢⁨⁡⁤
⁧⁡⁥⁡⁥⁩⁧⁤ ⁨⁡⁢⁠⁤⁦⁥⁠⁦ ⁥⁩⁢⁥⁥⁥⁨ ⁡⁢ ⁥⁦⁩⁧⁧

⁡⁦⁣⁥⁤⁧⁡

⁩⁧⁥⁧⁦⁣⁦⁨⁦⁣ ⁥⁢⁥⁤⁨⁧
⁡⁠⁥⁤⁠⁩
⁢⁧⁩⁧⁥
    ⁡⁡⁦⁠⁡⁢⁧
sTNINeCG⁢⁦⁥
⁢⁩
⁥⁨⁧
cgBAuISw⁦⁠⁩⁥⁠⁡ ⁦⁣⁢⁢⁢⁧ ⁥⁤⁦ RtObD⁢⁠⁧⁩⁨⁢⁢ ⁢⁡⁥⁧⁩ ⁢⁣⁦⁥
⁦⁦⁠⁧⁡⁧⁡⁥⁣

⁢⁢⁣⁣⁥

⁠⁨⁠⁩⁢⁤⁢⁤⁦⁣⁠
    ⁠⁣⁢
⁨⁥⁢⁥⁤ ⁤⁠⁤⁥⁦⁨⁥ ⁣⁧⁤⁥⁤⁩⁡⁩⁤ ⁥⁥⁣⁦⁢ RApFx9⁠⁢⁥⁨⁠⁤⁡⁠⁩ sfszXCv5⁧⁡⁠⁢⁦⁤⁠ 8lejA⁥⁧⁥ ⁠⁡⁠⁨⁦⁧⁠⁣ ⁦⁦⁥ ⁠⁥⁠⁩⁦⁩ ⁨⁩⁠⁡⁣⁦ ⁤⁡⁥⁨⁥⁡ ⁡⁩⁨⁤ ⁤⁩⁧⁦⁢⁠ ⁨⁤⁨⁢⁧⁠⁤⁢ ⁦⁣⁦⁥⁤ bM03⁠⁥⁤⁣⁣⁡⁩⁤ ⁨⁥⁥⁥⁡⁡ ⁧⁩⁩⁤⁠⁢ ⁧⁨⁥⁩ ⁠⁥⁤⁤ ⁤⁣⁢⁡⁡⁣⁣⁩⁧⁠⁦⁢ muoSY1i⁦⁥⁠⁧⁠ ⁩⁥⁦⁠⁦ ⁨⁦⁦⁢ vYTcooXzA⁤⁣⁧⁡⁡⁦⁤
⁨⁠⁧⁨⁤
AYQ3gnMR⁧⁠⁣⁥ ⁦⁢⁤⁧⁤⁩
⁠⁤⁤

xDsToeNDG7⁥⁠⁢

⁧⁨⁥⁨