新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > OpenEM 簡介和基于 OpenEM 的大矩陣乘實現

        OpenEM 簡介和基于 OpenEM 的大矩陣乘實現

        作者: 時間:2018-09-06 來源:網絡 收藏

        本文引用地址:http://www.104case.com/article/201809/388587.htm

        7. 配置 preload 門限,參見本文 1.2 節的敘述。

        2.2.2 創建生產者/消費者場景

        前面介紹過,在 OpenEM 中,消費者就是 execution object,溝通生產者和消費者的管道就是queue。本小節介紹怎樣創建 execution object 和 queue 以及怎樣把它們關聯起來。 關于怎樣產生 event,本文在下一小節描述。OpenEM 有下列 API 供應用調用:

        • 調用 em_eo_create()可以創建 execution object

        • 調用 em_queue_create()可以創建 queue

        • 調用 em_eo_add_queue()可以把 queue 和 execution object 映射起來

        本演示用例通過參數配置表列出 execution object, queue group object 和 queue object 的參數,然后通過解析函數解析配置表再調用 OpenEM的 API,這樣各個軟件對象的參數在配置表中一目了然,代碼的可讀性較好。圖 5 是本演示用例的映射關系。

        需要注意的是 coremask 總共有 64 個比特,但是目前 6678 最多也只有 8 個 DSP 核。所以大量 mask 比特是用不到的,目前。核 0~7 對應的 mask 比特是位于 byte[4]的 bit0:7

        需要注意的是 queue 到 execution object 的映射是通過 receiver 函數關聯起來,如紅色高亮顯示部分。

        初始化job的偽代碼如下:

        2.2.3 產生 event

        本文的演示用例把 matrix Y 切分成了 128 個 2048*16 的子塊,每個 event 對應一個子塊。Event被發送給 execution object 以后,receive 函數計算 Matrix X 乘與 matrix Y block,即 100*2048 ×2048*16 的矩陣乘,產生 100*16 個輸出。event 的產生包括下面幾個簡單步驟:

        • 調用 em_alloc 函數,從 public pool 獲取 free 的 event 描述符并且 enable preloading。

        • 把待處理的數據緩沖區掛到描述符上,也就是把描述符的 buffer 指針指向這個數據緩沖區。

        • 在描述符的 software info 域填上 job index。

        • 調用 em_send,把 event 發送到對應的 queue,也就是 proc queue。

        下面是產生 event 的代碼:

        需要注意的是 Event 產生的時候,它被哪一個 execution object 處理還沒有確定。因為 execution object 只是和 queue 關聯的。當把 event 發送到一個 queue 的時候,負責處理 event 的 execution object 就確定了。所以在調用 em_send()發送 event 到 queue 的時候參數之一就是要發送到的queue 的 handler。

        2.2.4 運行和 exit

        如前所述,“矩陣乘 event”是通過 proc queue 發給 scheduler 的,所以它被 proc queue 映射到mat_mpy calc 這個 execution object 上。Dispatcher 收到這個 event 后就調用“mat_mpy calc”對應的 receiver 函數計算矩陣相乘。因為 proc queue 所屬的 queue group 是映射到所有 DSP 核的,所以 128 個“矩陣乘 event”是在所有核上并行處理的。每個核處理完 event 后就把它釋放回global free pool。這樣這個 event 又成為一個 free 的 event。

        如 2.2.3 節所述,主核可以通過查詢 global free pool 的描述符個數是否恢復來判斷是否所有“矩陣乘 event”已經處理完。

        當所有“矩陣乘 event”處理完后,主核再產生 8 個“exit event”發送到 exit queue。理論上scheduler 可以把 exit job 調度給任意一個核,而不會保證每個核一個 exit job。所以 exit job 中的處理比較特殊。exit job 的 receiver 函數直接執行系統調用 exit(0)。這樣就不會返回到 Dispatcher,也不會再發出 prefetch command。而另一方面,scheduler 是在收到 DSP 核的 prefetch command 以后才把 event 調度給這個核的。這個機制保證了每個核收到且僅收到一個“exit event”。

        在 exit job 的 receiver 函數中,主核執行的分支稍有差異。主核需要先做完結果的校驗再執行系統調用 exit(0)。所以在板上運行是會觀察到其他核很快(小于 1s)就從 run 狀態轉換到 abort 狀態,而主核保持 run 了很長時間(大約 50s)才進入 abort 狀態。原因是:在主核上執行結果驗證工作時產生校驗結果的函數計算耗時比較長。

        下面是 exit job 的 receiver 函數的代碼主干:

        2.3 基于 OpenEM 的大矩陣乘性能測試結果

        2.3.1 算法代碼和 cycle 數的理論極限

        設 r1 是 X 矩陣的行數,c1 是 X 矩陣的列數,c2 是 Y 矩陣的列數。在我們的演示用例中 r1 =100, c1 = 2048, c2 = 2048。如前所述,Receiver 函數要計算 100*2048 × 2048*16 的矩陣乘,對應下面的偽代碼:

        循環內核是 4 個 cycle。 如果只考慮循環內核消耗的 cycle 數,計算 100*2048 × 2048*16 的矩陣乘需要的 cycle 數是 100/2*16/2*2048/4*4 = 819,200 cycle。整個 X*Y=Z 包括計算 128 個這樣的矩陣乘。所以總的 cycle 數是 819,200*128 = 104,857,600 cycles。在 1Ghz 的 C66 核上這相當于104.8ms。但是我們的上述理論計算沒有考慮循環的前后綴消耗的 cycle 數,也沒有考慮 cache miss stall 的等待時間。在 6678EVM 板的單個 DSP 核上實測,計算 X*Y=Z 消耗的實際時間是190,574,214 cycles。相當于 190ms。



        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 武清区| 元朗区| 莆田市| 湟源县| 柯坪县| 商南县| 抚顺县| 尼玛县| 昭觉县| 朔州市| 青州市| 德令哈市| 宝鸡市| 荔波县| 尚志市| 乌拉特前旗| 日喀则市| 凤翔县| 施秉县| 拉萨市| 尚志市| 托克逊县| 大丰市| 突泉县| 长治市| 金平| 鹿邑县| 吉安市| 南平市| 陵川县| 商丘市| 长岭县| 临湘市| 长宁区| 武隆县| 新巴尔虎右旗| 华蓥市| 新晃| 勃利县| 金溪县| 海口市|