91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

有關(guān) Dataflow 指令的原理

電子設(shè)計 ? 來源:電子設(shè)計 ? 作者:電子設(shè)計 ? 2022-02-09 10:34 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本文轉(zhuǎn)載自:XILINX開發(fā)者社區(qū)微信公眾號

提取實現(xiàn)任務級 (task_level) 的硬件并行算法是設(shè)計高效的HLS IP內(nèi)核的關(guān)鍵。

在本文中,我們將重點放在如何能夠在不需要特殊的庫或類的情況下修改代碼風格以實現(xiàn)C代碼實現(xiàn)并行性。Xilinx HLS 編譯器的顯著特征是能夠?qū)⑷蝿占墑e的并行性和流水線與可尋址的存儲器 PIPO或 FIFO相結(jié)合。本文首先概述可以獲取任務并行的前提條件,然后以DAG(directedacyclic graph) 代碼為例,挖掘其中使用 fork-join 并行性,并結(jié)合使用 ping- pong buffer 啟用了一種基于握手的任務級粗粒度的流水線形式。

我們理解任務級并行的時候可以想象成這樣一個場景,每一個計算任務都是時間軸上向前奔跑的馬車,馬車與馬車之間傳輸?shù)呢浳锞拖袷怯嬎銛?shù)據(jù),他們需要管道去連接即 FIFO 和 PIPO ,FIFO 是一個先進先出存儲器也就是說使用這樣的管道傳輸數(shù)據(jù)的時候,數(shù)據(jù)進出的順序不可以改變。而 PIPO 就是一個可尋址的存儲器管道,數(shù)據(jù)在任務之間進出的順序可以改變。

最糟糕的狀態(tài)是什么?馬車在時間線上順序出發(fā),A 馬車到達終點后 B 再出發(fā)以此類推,就像是 CPU 中的單進程順序執(zhí)行模式一樣,而FPGA中有可供并行化執(zhí)行的數(shù)據(jù)傳輸管道,更多的資源就像是跑道一樣,所以這個狀態(tài)效率是最低的。

那么先做一點點改進,我們分析發(fā)現(xiàn) B 和 C 馬車不享有任何公用的數(shù)據(jù)或存儲計算資源,也就是他們完全可以在 A 結(jié)束后并行執(zhí)行,最后再執(zhí)行 D,這種并行情況中含有順序和并行兩種模式,我們稱之為交叉并行 (fork-joinparallelism)。 但是下一次進程仍然是順序執(zhí)行的。

繼續(xù)深入可以發(fā)現(xiàn),四輛馬車在跑完各自的任務后都有一段的閑置時間,提高吞吐量和資源重復利用也很明顯是息息相關(guān)的。實現(xiàn)了進程之間的流水線執(zhí)行的結(jié)果就如下圖,每一輛馬車在不同的進程中連續(xù)執(zhí)行任務,向前奔跑,重復利用資源的同時它提升了吞吐量進而極大的減小了完成多個進程后的延遲。

最理想的狀態(tài)時什么?就是馬車盡可能的一個挨著一個一起出發(fā),并行奔跑,大家先后到達終點完成計算,在奔跑的過程中數(shù)據(jù)通過管道也完成了遷移,最終計算完的數(shù)據(jù)在最后一輛馬車到達終點的時候產(chǎn)出。下圖我們可以看到 B 和 C 開始執(zhí)行的時間提前了,并沒有等到A完全執(zhí)行完畢,這和數(shù)據(jù)依賴息息相關(guān),也就是說我們進一步挖掘并行性的路上發(fā)現(xiàn):ABC 三輛馬車都可以在增加馬車數(shù)量 (擴增資源) ,建立數(shù)據(jù)管道的并行執(zhí)行的前提下實現(xiàn)了。我們用資源換取了更大的并行性,這就是繼續(xù)挖掘并行性上需要付出的代價。

奔跑的馬車帶著我們理解了任務級流水線的優(yōu)化之路,下面我們結(jié)合代碼看一看HLS工具會在哪些情況下阻止 dataflow 的實現(xiàn)。

在我們談及 dataflow 的優(yōu)化之前,我們先去了解在 HLS 提醒你報錯的方式,其中修改屬性config_dataflow-strict_mode (off | error | warning) 指令可以控制報錯指令的級別,一般情況下默認是 warning 級別的報錯,主要看我們的并行性需求。

以下是阻止任務級別并行性的常見情況:

1. 單產(chǎn)出單消耗模型違例(Single-producer-consumerviolations)

為了使 VitisHLS 執(zhí)行 DATAFLOW 優(yōu)化,任務之間傳遞的所有元素都必須遵循單產(chǎn)出單消耗模型。每個變量必須從單個任務驅(qū)動,并且只能由單個任務使用。在下面的代碼示例中是典型的單產(chǎn)出單消耗模型違例,單一的數(shù)據(jù)流 temp1 同時被 Loop2 和 Loop3 消耗。要解決這個問題很容易,就是將兩個任務都要消耗的數(shù)據(jù)流復制成兩個,如右圖的 Split 函數(shù)。當 temp1數(shù)據(jù)流被復制為 temp2 和 temp3 后,LOOP1,2,3 就可以實現(xiàn)任務級流水線了。

void foo(int data_in[N], int scale, int data_out1[N], int data_out2[N]) { int temp1[N]; Loop1: for(int i = 0; i < N; i++) { temp1[i] = data_in[i] * scale; } Loop2: for(int j = 0; j < N; j++) { data_out1[j] = temp1[j] * 123; } Loop3: for(int k = 0; k < N; k++) { data_out2[k] = temp1[k] * 456; } }void Split (in[N], out1[N], out2[N]) { // Duplicated data L1:for(int i=1;i

2. 旁路任務 Bypassing Tasks

正常情況下我們期望流水線任務是一個接著一個的產(chǎn)出并消耗,然而像下面這個例子中,Loop1 產(chǎn)生了 Temp1和Temp2 兩個數(shù)據(jù)流,但是在下一個任務 Loop2 中只有 temp1 參與了運算,而 temp2 就被旁支了。Loop3 任務的執(zhí)行依賴 Loop2 任務產(chǎn)生的 temp3 數(shù)據(jù),所以 Loop2 和 Loop3 因為數(shù)據(jù)依賴的關(guān)系無法并行執(zhí)行。

void foo(int data_in[N], int scale, int data_out1[N], int data_out2[N]) { int temp1[N], temp2[N]. temp3[N]; Loop1: for(int i = 0; i < N; i++) { temp1[i] = data_in[i] * scale; temp2[i] = data_in[i] >> scale; } Loop2: for(int j = 0; j < N; j++) { temp3[j] = temp1[j] + 123; } Loop3: for(int k = 0; k

3. 任務間雙向反饋 Feedbackbetween Tasks

假如說當前任務的結(jié)果,需要作為之前一個任務的輸入的話,就形成了任務之間的數(shù)據(jù)反饋,它打亂了流水線從上級一直往下級輸送數(shù)據(jù)流的規(guī)則。這時候 HLS 就會給出警告或者報錯,有可能完成不了 dataflow 優(yōu)化了。有一種特例是支持的:使用 hls::stream 格式的數(shù)據(jù)流反饋。

我們分析以下代碼的內(nèi)容:

當?shù)谝粋€程序 firstProc 執(zhí)行的時候,hls::stream 格式的數(shù)據(jù)流 forwardOUT 被寫入了初始化為10的數(shù)值 fromSecond 。由于 hls::stream 格式的數(shù)據(jù)本身不支持初始化操作,所以這樣的操作避免了違反單產(chǎn)出單消耗原則。之后的迭代里,firstProc 通過 backwardIN 接口從 hls :: stream 讀取數(shù)值寫入 forwardOUT 中。

在第二個程序 secondProc 執(zhí)行的時候,secondProc 讀取 forwardIN 上的值,將其加1,然后通過按執(zhí)行順序倒退的反饋流將其發(fā)送回 FirstProc。從第二次執(zhí)行開始,firstProc 將使用從流中讀取的值進行計算,并且兩個過程可以使用第一次執(zhí)行的初始值,通過正向和反饋通信永遠保持下去。這種交互式的反饋中,包含數(shù)據(jù)流的雙向反饋機制,但是它就像貨物一直在從左手倒到右手再從右手倒到左手一樣,可以不違反 Dataflow 的規(guī)范,一直進行下去。

#include "ap_axi_sdata.h" #include "hls_stream.h" void firstProc(hls::stream &forwardOUT, hls::stream &backwardIN) { static bool first = true; int fromSecond; //Initialize stream if (first) fromSecond = 10; // Initial stream value else //Read from stream fromSecond = backwardIN.read(); //Feedback value first = false; //Write to stream forwardOUT.write(fromSecond*2); } void secondProc(hls::stream &forwardIN, hls::stream &backwardOUT) { backwardOUT.write(forwardIN.read() + 1); } void top(...) { #pragma HLS dataflow hls::stream forward, backward; firstProc(forward, backward); secondProc(forward, backward); }

4. 含有條件判斷的任務流水

DATAFLOW 優(yōu)化不會優(yōu)化有條件執(zhí)行的任務。下面的示例展現(xiàn)了這個違例。在此示例中,有條件地執(zhí)行 Loop1 和 Loop2 會阻止 Vitis HLS 優(yōu)化這些循環(huán)之間的數(shù)據(jù)流,因為 sel 條件直接控制了任務中的數(shù)據(jù)有可能不會從一個循環(huán)流到下一個循環(huán)。

void foo(int data_in1[N], int data_out[N], int sel) { int temp1[N], temp2[N]; if (sel) { Loop1: for(int i = 0; i < N; i++) { temp1[i] = data_in[i] * 123; temp2[i] = data_in[i]; } } else { Loop2: for(int j = 0; j < N; j++) { temp1[j] = data_in[j] * 321; temp2[j] = data_in[j]; } } Loop3: for(int k = 0; k < N; k++) { data_out[k] = temp1[k] * temp2[k]; } }

但是我們都知道,其實這些任務之間存在條件判斷和選擇是非常常見的情況,只需要稍微改變代碼風格就可以既保留條件判斷,又完成任務流水。為了確保在所有情況下都執(zhí)行每個循環(huán),我們將條件語句下變化的 Temp1 移入第一個循環(huán)。這兩個循環(huán)始終執(zhí)行,并且數(shù)據(jù)始終從一個循環(huán)流向下一個循環(huán)。

void foo(int data_in[N], int data_out[N], int sel) { int temp1[N], temp2[N]; Loop1: for(int i = 0; i < N; i++) { if (sel) { temp1[i] = data_in[i] * 123; } else { temp1[i] = data_in[i] * 321; } } Loop2: for(int j = 0; j < N; j++) { temp2[j] = data_in[j]; } Loop3: for(int k = 0; k < N; k++) { data_out[k] = temp1[k] * temp2[k]; } }

5. 有多種退出機制的循環(huán)

含有多種退出機制的循環(huán)不能被包含在流水線區(qū)域內(nèi),我們來數(shù)一數(shù) Loop2 一共有多少種循環(huán)退出條件:

1. 由 for 循環(huán)定義的 K>N 的情況;

2. 由 switch 條件定義的 default 情況;

3. 由 switch 條件定義的 continue 情況

由于循環(huán)的退出條件始終由循環(huán)邊界定義,因此使用 break 或 continue 語句將禁止在DATAFLOW 區(qū)域中使用循環(huán)。

void multi_exit(din_t data_in[N], dsc_t scale, dsel_t select, dout_t data_out[N]) { dout_t temp1[N], temp2[N]; int i,k; Loop1: for(i = 0; i < N; i++) { temp1[i] = data_in[i] * scale; temp2[i] = data_in[i] >> scale; } Loop2: for(k = 0; k < N; k++) { switch(select) { case 0: data_out[k] = temp1[k] + temp2[k]; case 1: continue; default: break; } } }

我們理解了可能阻止任務流水線的 5 種經(jīng)典情況后,我們最后推出適用于 Vitis HLS 的Dataflow 優(yōu)化的兩種規(guī)范形式 (canonical forms) ,一種直接應用于函數(shù),一種應用于 for循環(huán)。我們可以發(fā)現(xiàn)規(guī)范形式嚴格遵守了單產(chǎn)出單消耗的規(guī)則。

1. 適用于子程序沒有被內(nèi)聯(lián) (inline) 的規(guī)范形式

void dataflow(Input0, Input1, Output0, Output1) { #pragma HLS dataflow UserDataType C0, C1, C2; func1(read Input0, read Input1, write C0, write C1); func2(read C0, read C1, write C2); func3(read C2, write Output0, write Output1); }

2. 適用于循環(huán)體內(nèi)的任務流水的規(guī)范形式:

對于 for 循環(huán) (其中沒有內(nèi)聯(lián)函數(shù)的地方),循環(huán)變量應具有:

a. 在 for 循環(huán)的標題中聲明初始值,并設(shè)置為 0。

b. 循環(huán)條件N是一個正數(shù)值常數(shù)或常數(shù)函數(shù)參數(shù)。

c. 循環(huán)的遞增量為1。

d. Dataflow 指令必須位于循環(huán)內(nèi)部。

void dataflow(Input0, Input1, Output0, Output1) { for (int i = 0; i < N; i++) { #pragma HLS dataflow UserDataType C0, C1, C2; func1(read Input0, read Input1, write C0, write C1); func2(read C0, read C0, read C1, write C2); func3(read C2, write Output0, write Output1); } }

有關(guān) Dataflow 指令的原理,設(shè)計準則和規(guī)范形式都在本文講解給大家了,更多設(shè)計例程可以參考Github(https://github.com/Xilinx/HLS-Tiny-Tutorials/tree/master/coding_dataflow... ),如有疑問歡迎交流!

審核編輯:何安

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Dataflow
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    6892
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    A64指令集通關(guān)筆記:加載與存儲指令全解析

    作為嵌入式 ?Linux? 開發(fā)者, A64? 指令集是我們繞不開的基本功。最近我在復習這部分內(nèi)容時,整理了一份帶思考題解答的筆記,希望能幫大家快速掌握核心要點。 ? 開篇:為什么必須啃下 A64
    的頭像 發(fā)表于 01-20 16:23 ?205次閱讀
    A64<b class='flag-5'>指令</b>集通關(guān)筆記:加載與存儲<b class='flag-5'>指令</b>全解析

    RISC-V高級指令融合如何實現(xiàn)性能密度躍升

    Synopsys ARC-V 處理器中的高級指令融合引入了一種新型機制,用于融合常見的 RISC-V 指令對,旨在提高處理器流水線效率,特別是針對資源受限的嵌入式處理器。通過融合來自不同功能單元的指令, 它將單發(fā)射、順序執(zhí)行的處
    的頭像 發(fā)表于 12-29 11:22 ?315次閱讀
    RISC-V高級<b class='flag-5'>指令</b>融合如何實現(xiàn)性能密度躍升

    RDMA設(shè)計10:指令控制單元設(shè)計?

    指令控制單元負責控制數(shù)據(jù)傳輸及 DMA 數(shù)據(jù)讀寫。該單元簡化了數(shù)據(jù)傳輸及DMA 操作,使得用戶可以更簡便的控制數(shù)據(jù)傳輸事務。指令控制單元的功能由指令控制寄存器組和指令狀態(tài)寄存器組成。
    的頭像 發(fā)表于 12-23 09:24 ?300次閱讀
    RDMA設(shè)計10:<b class='flag-5'>指令</b>控制單元設(shè)計?

    歐盟CE-RED指令介紹

    歐盟CE-RED指令,全稱是RadioEquipmentDirective(無線電設(shè)備指令),指令編號為2014/53/EU,是歐盟針對所有帶無線發(fā)射功能設(shè)備制定的一項強制性法規(guī)。它是歐盟CE認證
    的頭像 發(fā)表于 11-05 14:01 ?712次閱讀
    歐盟CE-RED<b class='flag-5'>指令</b>介紹

    浮點數(shù)指令的添加——長指令寫回仲裁

    =在增加浮點數(shù)指令時,我們會遇到一些需要寫回寄存器的指令,此時就需要對原先的寫回功能模塊做更改。 寫回功能主要集中在這兩個模塊中 e203_exu_longpwbck.v長指令寫回仲裁
    發(fā)表于 10-24 07:09

    浮點數(shù)指令添加——長指令寫回仲裁

    浮點數(shù)指令添加——長指令寫回仲裁 在增加浮點數(shù)指令時,我們會遇到一些需要寫回寄存器的指令,此時就需要對原先的寫回功能模塊做更改。 寫回功能主要集中在這兩個模塊中
    發(fā)表于 10-24 06:07

    NICE指令的完整執(zhí)行過程

    NICE指令的完整執(zhí)行過程如下: 1、主處理器的譯碼單元提供EXU級譯碼得到指令的操作碼,以判斷其是否屬于默認的自定義指令組。 如果該指令屬于自定義
    發(fā)表于 10-23 07:25

    浮點指令擴展中16位指令的處理

    RISC-V支持16位壓縮格式,壓縮格式立即數(shù)位數(shù)更少,能使用的寄存器也比較少,有些指令只能用常用8個整數(shù)寄存器(x8-x15)或者(f8-f15)。16 位指令只對匯編器和鏈接器可見,并且是否以短
    發(fā)表于 10-20 11:02

    Linux環(huán)境下div指令、divu指令測試異常怎么解決?

    由于團隊修改了muldiv指令,需要測試div指令、divu指令是否功能正常: rv32um-p-div: 意外的,程序會產(chǎn)生自檢報錯(實際上這個報錯在原工程中也會出現(xiàn)),通過info我們可以看到
    發(fā)表于 10-20 06:07

    西門子SMART200脈沖指令資料

    西門子SMART200脈沖指令
    發(fā)表于 07-29 17:29 ?0次下載

    通用MCU語音芯片支持串口+AT指令485通訊

    文檔簡單介紹AD24N的性能參數(shù)、串口通訊指令、應用方向、等內(nèi)容
    的頭像 發(fā)表于 07-24 11:35 ?708次閱讀
    通用MCU語音芯片支持串口+AT<b class='flag-5'>指令</b>485通訊

    步進電機控制指令詳解

    這些指令主要是針對用 PLC 直接聯(lián)動伺服放大器,目的是可以不借助其他擴展設(shè)備(例如1GM 模塊)來進行簡單的點位控制, 使用這些指令時最好配合三菱的伺服放大器 (如 MR-J2)。然而,我們也可以用這些指令來控制步進電機的運行
    的頭像 發(fā)表于 06-12 10:33 ?1983次閱讀
    步進電機控制<b class='flag-5'>指令</b>詳解

    NVME控制器設(shè)計之指令控制

    指令控制模塊由一個指令信息緩存, 一個指令組裝狀態(tài)機和一個 ID 池組成。 指令信息緩存中存放著由系統(tǒng)控制模塊寫入的待處理指令信息;
    的頭像 發(fā)表于 04-24 10:22 ?826次閱讀
    NVME控制器設(shè)計之<b class='flag-5'>指令</b>控制

    普源示波器遠程控制SCPI指令的應用

    Commands for Programmable Instruments)指令作為標準化的控制語言,為普源示波器的遠程控制提供了強有力的支持。本文將深入探討普源示波器遠程控制SCPI指令的應用,包括其基本概念、常用指令、應用
    的頭像 發(fā)表于 04-22 15:55 ?1259次閱讀
    普源示波器遠程控制SCPI<b class='flag-5'>指令</b>的應用

    CPU的各種指令和執(zhí)行流程

    在集成電路設(shè)計中,CPU的指令是指計算機中央處理單元(CPU)用來執(zhí)行計算任務的基本操作指令集。這些指令是CPU能夠理解并執(zhí)行的二進制代碼,它們在計算機內(nèi)部由硬件控制并按順序執(zhí)行,從而實現(xiàn)計算、控制
    的頭像 發(fā)表于 04-18 11:24 ?2616次閱讀