1、OpenEM 簡(jiǎn)介
OpenEM 的全稱是 Open Event Machine。它是 TI 開(kāi)發(fā)的可應(yīng)用于 Keystone 多核 DSP 的multicore runtime system library。OpenEM 的目的是在多核上有效的調(diào)度,分發(fā)任務(wù),實(shí)現(xiàn)動(dòng)態(tài)的負(fù)載平衡?;?OpenEM,用戶可以很容易的把原來(lái)的單核應(yīng)用移植到 Keystone 多核芯片。需要注意的是 OpenEM 目前只能把任務(wù)調(diào)度分發(fā)到同一個(gè) DSP 的多個(gè)核上,不能跨 DSP 調(diào)度分發(fā)。 OpenEM不依賴于 BIOS。它可以在芯片上裸跑,代碼精簡(jiǎn),效率高。而且,OpenEM不同于業(yè)界已經(jīng)有 OpenMP 和 OpenCL 等開(kāi)放式的 multi-core runtime systems。它是針對(duì)嵌入式系統(tǒng)的設(shè)計(jì),更能滿足嵌入式設(shè)計(jì)的實(shí)時(shí)性要求。TI 的 keystone 架構(gòu)多核芯片中有 Multicore Navigator。它由 Queue Manager(簡(jiǎn)稱為 QMSS)和一系列 Packet DMA engine 構(gòu)成。OpenEM就是基于這套硬件系統(tǒng)構(gòu)建的。例如,OpenEM 的 scheduler 是運(yùn)行在 QMSS 的 PDSP(QMSS內(nèi)部的 RISC 處理器)上的。OpenEM的 preload 功能是通過(guò) QMSS 的 packet DMA 實(shí)現(xiàn)的。熟悉QMSS 的編程對(duì)學(xué)習(xí) OpenEM 很有幫助。OpenEM 是 MCSDK 的一個(gè)組件。它還在不斷的發(fā)展改進(jìn)中。本文對(duì) OpenEM 的介紹以及演示用例都是基于 BIOS MCSDK 2.01.02 的 OpenEM 1.0.0.2。
1.1 OpenEM 的軟件對(duì)象
下面通過(guò)列表和圖示介紹了 OpenEM的主要軟件對(duì)象。表 1 是 OpenEM 的主要軟件對(duì)象的列表。
需要注意的是,本文介紹的 OpenEM 的運(yùn)行模式是:Scheduler 運(yùn)行在 PDSP,Dispatcher 是“run to completion ”模式。
圖 1 是一個(gè)軟件對(duì)象關(guān)系圖,顯示出了表 1 中列舉的軟件對(duì)象。定義了 2 個(gè) queue group,5 個(gè)queue 和 3 個(gè) execution object。Queue group1 的 core mask 對(duì)應(yīng)核 0 和 1。所以來(lái)自 queue1,2,3,4 的 event 只能在核 0 和核 1 上執(zhí)行,因?yàn)檫@些 queue 屬于 queue group1。Queue group2 的 core mask 對(duì)應(yīng)核 2 和 3。所以來(lái)自 queue5 的 event 只能在核 2 和核 3 上執(zhí)行,因?yàn)閝ueue5 屬于 queue group2。execution object 1 和 queue 1,2,3 映射關(guān)聯(lián)。execution object 2 和queue 4 映射關(guān)聯(lián)。execution object 3 和 queue 5 映射關(guān)聯(lián)。圖中的藍(lán)線表示了 event 的行徑,紅線表示 command 的行徑。圖中的 SD queue 是 hardware queue,它不是一個(gè)軟件對(duì)象而是OpenEM內(nèi)部的組件。
1.2 OpenEM 的兩個(gè)重要概念
OpenEM中有兩個(gè)容易混淆的重要概念:prefetch 和 preload。
? Prefetch 是指每個(gè) DSP 核向 scheduler 發(fā)命令,告訴 scheduler“本核已經(jīng)空閑了,可以分配新的工作給本核了”。只有收到一個(gè)核的 prefetch 命令,scheduler 才會(huì)調(diào)度新的 event 給這個(gè)核。如果 DSP 核不發(fā)出 prefetch 命令,它就不會(huì)被分派任務(wù)。這是 OpenEM 的 scheduler的基本調(diào)度原則。
? Preload 和 event 的屬性有關(guān)。通常,event 的數(shù)據(jù)是位于 DDR 的。如果 DSP 核直接訪問(wèn)DDR 效率會(huì)比較低。所以,OpenEM 可以把 event 的數(shù)據(jù)通過(guò) QMSS 的 packet DMA 搬到DSP 核的 local L2。這個(gè)搬移的過(guò)程就是 preload。每個(gè) event 的數(shù)據(jù)是否做 preload 是可配的。每個(gè) event 在創(chuàng)建的時(shí)候都可以指定一個(gè) preload 屬性。Event 的 preload 屬性可以是:
– Preload disable, 即不做預(yù)搬移
– Preload up to sizeA,即做預(yù)搬移,但是最多只搬 sizeA bytes
– Preload up to sizeB,即做預(yù)搬移,但是最多只搬 sizeB bytes
– Preload up to sizeC,即做預(yù)搬移,但是最多只搬 sizeC bytes
– 其中 SizeA,SizeB 和 SizeC 是常數(shù),在 OpenEM 初始化的時(shí)候可以配置。
1. 3 OpenEM 的常用 API cycle 數(shù)
OpenEM的附帶開(kāi)銷(xiāo)是應(yīng)用最關(guān)注特性之一。所以我們實(shí)測(cè)了 OpenEM 常用 API 的 cycle 數(shù)如表2。需要注意的是:由于 OpenEM會(huì)負(fù)責(zé) cache 一致性的維護(hù),而有些 API 的處理過(guò)程中含有cache 一致性的維護(hù)操作。所以這些 API 的調(diào)用 cycle 數(shù)很大程度上取決于它對(duì)多大的數(shù)據(jù)緩沖區(qū)做了 cache 一致性的維護(hù)。本文測(cè)試這些 cycle 的場(chǎng)景使用的數(shù)據(jù)緩沖區(qū)的大小是是 4096 words(32bit)。
2、基于 OpenEM 的大矩陣乘實(shí)現(xiàn)
大矩陣相乘的目的是計(jì)算 X*Y = Z
矩陣 X 是(100 × 2048 )的浮點(diǎn)實(shí)數(shù)矩陣。
矩陣 Y 是(2048 × 2048 )的浮點(diǎn)實(shí)數(shù)矩陣。
矩陣 Z 是(100 × 2048 )的浮點(diǎn)實(shí)數(shù)矩陣。
由于矩陣 Y 的數(shù)據(jù)量很大,所以在多核 DSP 上可以把它拆分成多個(gè)子塊,交給多個(gè) DSP 核并行計(jì)算。如圖 2 所示。
2.1 基于 OpenEM 的大矩陣乘方案設(shè)計(jì)
2.1.1 Memory 使用
Shannon DSP (6678)的內(nèi)存系統(tǒng)包括片內(nèi)的 LL2(local L2)和 SL2(shared L2)。加上片外的 DDR。LL2 的 size 是 512 Kbytes,每個(gè)核有一份 LL2。 SL2 的 size 是 4Mbytes,8 個(gè)核共享 SL2。DDR size 和硬件板卡設(shè)計(jì)有關(guān),一般在 1G bytes 以上。 C66x 核對(duì) LL2 的訪問(wèn)效率最高,對(duì) SL2 的訪問(wèn)效率稍差,對(duì) DDR 的訪問(wèn)效率最低?;诙喾N存儲(chǔ)區(qū)間的不同特性,我們對(duì)數(shù)據(jù)存儲(chǔ)位置按如下規(guī)劃(參見(jiàn)圖 3):
– 矩陣 X 的 size 是 800 Kbytes,存儲(chǔ)是 shared L2
– 矩陣 Y 的 size 是 16 Mbytes,存儲(chǔ)是 DDR
– 矩陣 Z 的 size 是 800 Kbytes,存儲(chǔ)是 shared L2
雖然矩陣 Y 存儲(chǔ)在 DDR,但是我們啟用了 OpenEM 的 preload 功能。Preload 就是通過(guò) QMSS 的 packet DMA 把待處理的 event 數(shù)據(jù)(通常位于 DDR)搬到被調(diào)度 core 的 LL2。所以 DSP 核運(yùn)行的時(shí)候不直接從 DDR 取數(shù)。這保證了 DSP 核的數(shù)據(jù)訪問(wèn)效率。
2.1.2 處理流程
OpenEM中要有一個(gè) DSP 核作為主核,其他核就是從核,主核要完成的工作較多。本文的演示用例中,核 0 是主核,核 1~7 是從核。主從核的分工差異如圖 4:
1. 初始化 QMSS 和 free pool。
2. OpenEM 的 global 初始化和 local 初始化。global 初始化是主核執(zhí)行。local 初始化是每個(gè)核各自執(zhí)行。Local 初始化要等 global 初始化完成才能開(kāi)始。所以,中間需要加一個(gè)barrier。Barrier 可以理解成一個(gè)同步點(diǎn),所有 DSP 核在這個(gè)點(diǎn)完成一次同步再繼續(xù)向下執(zhí)行。本演示用例的 Barrier 是通過(guò)共享內(nèi)存的軟件信號(hào)量實(shí)現(xiàn)的。
3. 主核構(gòu)造生產(chǎn)者/消費(fèi)者場(chǎng)景并產(chǎn)生待處理的 event。生產(chǎn)者在 OpenEM 中不是一個(gè)軟件對(duì)象。我們可以把產(chǎn)生 event 并發(fā)送到 queue 的函數(shù)認(rèn)為是生產(chǎn)者。消費(fèi)者就是 execution object,溝通生產(chǎn)者和消費(fèi)者的管道就是 queue。構(gòu)造生產(chǎn)者/消費(fèi)者場(chǎng)景就是創(chuàng)建execution object 和 queue 并且把它們關(guān)聯(lián)起來(lái)。
4. 主核和從核進(jìn)入 event 處理的過(guò)程。
5. 主核檢測(cè)到所有 event 都處理完成后為每個(gè) DSP 核(包括它自己)產(chǎn)一個(gè) exit job。
6. 主核和從核處理 exit job。從核直接調(diào)用 exit(0)退出。主核先做結(jié)果驗(yàn)證然后調(diào)用 exit(0)退出。
本文演示用例實(shí)現(xiàn)的幾個(gè)特點(diǎn)是:
? OpenEM 的 free pool 是由用戶初始化的。在初始化 free pool 的時(shí)候 event 描述符不指向數(shù)據(jù)緩沖區(qū)。等分配了一個(gè) event 的時(shí)候再在這個(gè) event 對(duì)應(yīng)的描述符上掛數(shù)據(jù)緩沖區(qū)。這樣可以避免不必要的數(shù)據(jù)拷貝(從 global buffer 拷貝到 event buffer)。
? 主核通過(guò)查詢 free pool 中的 event 個(gè)數(shù)是否恢復(fù)回初始值來(lái)判斷是否所有“矩陣乘 event”都處理。因?yàn)椋?/p>
– Free pool 在初始化以后有 N 個(gè) free event,
– 從中分配了若干個(gè) event 后,free event 就減少了相應(yīng)的個(gè)數(shù),
– 每個(gè) core 每處理完一個(gè) event 就把這個(gè) event 回收到 free pool,free pool 的 event 個(gè)數(shù)就加一。當(dāng) free pool 的 event 個(gè)數(shù)恢復(fù)回 N,就說(shuō)明所有 event 都處理完了。
2.2 基于 OpenEM 的大矩陣乘實(shí)現(xiàn)
在初始化 OpenEM之前首先要做 multicore Navi
gator 的初始化。包括:PDSP firmware 的download, Link RAM 的初始化, Memory region 的初始化還有 free pool (也就是 free descriptorqueue)的初始化。這不屬于本文介紹的范疇,本文直接介紹 OpenEM的初始化。
2.2.1 OpenEM 的 Global 初始化
OpenEM的 global 初始化通過(guò)調(diào)用 API 函數(shù) ti_em_init_global()完成的。這個(gè) API 的入?yún)⑹窍旅嫠镜慕Y(jié)構(gòu)體。其中所列的參數(shù)是本文的演示用例使用的配置參數(shù)。本文針對(duì)每個(gè)參數(shù)的作用做了注釋。了解了參數(shù)了含義,就能了解 OpenEM 的 global 初始化的大致做了些什么。
注釋:
1. OpenEM要使用 hardware queue 資源。hw_queue_base_idx 用來(lái)指定 OpenEM 從哪個(gè)hardware queue 開(kāi)始可用。
2. OpenEM 的少量操作需要多 DSP 核訪問(wèn)共享的數(shù)據(jù)結(jié)構(gòu)。是通過(guò) hardware semaphore 實(shí)現(xiàn)多核lock/unclock 的。所以通過(guò) hw_sem_idx 告訴 OpenEM該使用哪一個(gè) hardware semaphore。
3. 指定 preload 使用的 QMSS packet DMA 的通道的起始索引。QMSS packet DMA 有 32 個(gè) RX/TX channel。在 OpenEM 中,每個(gè) DSP core 要占用一個(gè) TX/RX channel。
4. 指定 preload 使用的 QMSS Tx queues 的起始索引。要和 dma_idx 對(duì)應(yīng)起來(lái)。QMSS 有 32 個(gè) TX queue,索引是 800~831。對(duì)應(yīng) QMSS packet DMA 的 TX channel 0~31。所以,如果前面配置的 dma_idx 是 0,那么這里配置的 dma_queue_base_idx 應(yīng)該是 800。
5. 指定 OpenEM local free pool 對(duì)應(yīng)的 free queue index。Local free pool 是和 preload 相關(guān)的。local free pool 在物理上是一個(gè) free descriptor queue。里面存儲(chǔ)著 2 個(gè) host 描述符。每個(gè)描述符對(duì)應(yīng)一個(gè) local L2 buffer。如果發(fā)生 preload,packet DMA 就從 free descriptor queue pop 描述符,然后把數(shù)據(jù)傳到描述符指向的 local L2 buffer。每個(gè) DSP 核有一個(gè) local free pool。例如,在我們的演示用例中 core0~7 對(duì)應(yīng)的 free descriptor queue 索引是 2050~2057。
6. 指定 OpenEM global free pool 的個(gè)數(shù)。每個(gè) global free pool 包括 4 個(gè)初始化參數(shù),例如{ globalFreePoolFdqIdx, TI_EM_COH_MODE_ON,TI_EM_BUF_MODE_GLOBAL_TIGHT,0}。參數(shù) 1是這個(gè) global free pool 對(duì)應(yīng)的 free queue index。接下來(lái)幾項(xiàng)是這個(gè) pool 中的 buffer 的屬性。Global free pool 是用來(lái)從中分配 free event 的。調(diào)用 em_alloc()的入?yún)⒅痪褪?free pool index。
7. 配置 preload 門(mén)限,參見(jiàn)本文 1.2 節(jié)的敘述。
2.2.2 創(chuàng)建生產(chǎn)者/消費(fèi)者場(chǎng)景
前面介紹過(guò),在 OpenEM 中,消費(fèi)者就是 execution object,溝通生產(chǎn)者和消費(fèi)者的管道就是queue。本小節(jié)介紹怎樣創(chuàng)建 execution object 和 queue 以及怎樣把它們關(guān)聯(lián)起來(lái)。 關(guān)于怎樣產(chǎn)生 event,本文在下一小節(jié)描述。OpenEM 有下列 API 供應(yīng)用調(diào)用:
? 調(diào)用 em_eo_create()可以創(chuàng)建 execution object
? 調(diào)用 em_queue_create()可以創(chuàng)建 queue
? 調(diào)用 em_eo_add_queue()可以把 queue 和 execution object 映射起來(lái)
本演示用例通過(guò)參數(shù)配置表列出 execution object, queue group object 和 queue object 的參數(shù),然后通過(guò)解析函數(shù)解析配置表再調(diào)用 OpenEM的 API,這樣各個(gè)軟件對(duì)象的參數(shù)在配置表中一目了然,代碼的可讀性較好。圖 5 是本演示用例的映射關(guān)系。
需要注意的是 coremask 總共有 64 個(gè)比特,但是目前 6678 最多也只有 8 個(gè) DSP 核。所以大量 mask 比特是用不到的,目前。核 0~7 對(duì)應(yīng)的 mask 比特是位于 byte[4]的 bit0:7
需要注意的是 queue 到 execution object 的映射是通過(guò) receiver 函數(shù)關(guān)聯(lián)起來(lái),如紅色高亮顯示部分。
初始化job的偽代碼如下:
2.2.3 產(chǎn)生 event
本文的演示用例把 matrix Y 切分成了 128 個(gè) 2048*16 的子塊,每個(gè) event 對(duì)應(yīng)一個(gè)子塊。Event被發(fā)送給 execution object 以后,receive 函數(shù)計(jì)算 Matrix X 乘與 matrix Y block,即 100*2048 ×2048*16 的矩陣乘,產(chǎn)生 100*16 個(gè)輸出。event 的產(chǎn)生包括下面幾個(gè)簡(jiǎn)單步驟:
? 調(diào)用 em_alloc 函數(shù),從 public pool 獲取 free 的 event 描述符并且 enable preloading。
? 把待處理的數(shù)據(jù)緩沖區(qū)掛到描述符上,也就是把描述符的 buffer 指針指向這個(gè)數(shù)據(jù)緩沖區(qū)。
? 在描述符的 software info 域填上 job index。
? 調(diào)用 em_send,把 event 發(fā)送到對(duì)應(yīng)的 queue,也就是 proc queue。
下面是產(chǎn)生 event 的代碼:
需要注意的是 Event 產(chǎn)生的時(shí)候,它被哪一個(gè) execution object 處理還沒(méi)有確定。因?yàn)?execution object 只是和 queue 關(guān)聯(lián)的。當(dāng)把 event 發(fā)送到一個(gè) queue 的時(shí)候,負(fù)責(zé)處理 event 的 execution object 就確定了。所以在調(diào)用 em_send()發(fā)送 event 到 queue 的時(shí)候參數(shù)之一就是要發(fā)送到的queue 的 handler。
2.2.4 運(yùn)行和 exit
如前所述,“矩陣乘 event”是通過(guò) proc queue 發(fā)給 scheduler 的,所以它被 proc queue 映射到mat_mpy calc 這個(gè) execution object 上。Dispatcher 收到這個(gè) event 后就調(diào)用“mat_mpy calc”對(duì)應(yīng)的 receiver 函數(shù)計(jì)算矩陣相乘。因?yàn)?proc queue 所屬的 queue group 是映射到所有 DSP 核的,所以 128 個(gè)“矩陣乘 event”是在所有核上并行處理的。每個(gè)核處理完 event 后就把它釋放回global free pool。這樣這個(gè) event 又成為一個(gè) free 的 event。
如 2.2.3 節(jié)所述,主核可以通過(guò)查詢 global free pool 的描述符個(gè)數(shù)是否恢復(fù)來(lái)判斷是否所有“矩陣乘 event”已經(jīng)處理完。
當(dāng)所有“矩陣乘 event”處理完后,主核再產(chǎn)生 8 個(gè)“exit event”發(fā)送到 exit queue。理論上scheduler 可以把 exit job 調(diào)度給任意一個(gè)核,而不會(huì)保證每個(gè)核一個(gè) exit job。所以 exit job 中的處理比較特殊。exit job 的 receiver 函數(shù)直接執(zhí)行系統(tǒng)調(diào)用 exit(0)。這樣就不會(huì)返回到 Dispatcher,也不會(huì)再發(fā)出 prefetch command。而另一方面,scheduler 是在收到 DSP 核的 prefetch command 以后才把 event 調(diào)度給這個(gè)核的。這個(gè)機(jī)制保證了每個(gè)核收到且僅收到一個(gè)“exit event”。
在 exit job 的 receiver 函數(shù)中,主核執(zhí)行的分支稍有差異。主核需要先做完結(jié)果的校驗(yàn)再執(zhí)行系統(tǒng)調(diào)用 exit(0)。所以在板上運(yùn)行是會(huì)觀察到其他核很快(小于 1s)就從 run 狀態(tài)轉(zhuǎn)換到 abort 狀態(tài),而主核保持 run 了很長(zhǎng)時(shí)間(大約 50s)才進(jìn)入 abort 狀態(tài)。原因是:在主核上執(zhí)行結(jié)果驗(yàn)證工作時(shí)產(chǎn)生校驗(yàn)結(jié)果的函數(shù)計(jì)算耗時(shí)比較長(zhǎng)。
下面是 exit job 的 receiver 函數(shù)的代碼主干:
2.3 基于 OpenEM 的大矩陣乘性能測(cè)試結(jié)果
2.3.1 算法代碼和 cycle 數(shù)的理論極限
設(shè) r1 是 X 矩陣的行數(shù),c1 是 X 矩陣的列數(shù),c2 是 Y 矩陣的列數(shù)。在我們的演示用例中 r1 =100, c1 = 2048, c2 = 2048。如前所述,Receiver 函數(shù)要計(jì)算 100*2048 × 2048*16 的矩陣乘,對(duì)應(yīng)下面的偽代碼:
循環(huán)內(nèi)核是 4 個(gè) cycle。 如果只考慮循環(huán)內(nèi)核消耗的 cycle 數(shù),計(jì)算 100*2048 × 2048*16 的矩陣乘需要的 cycle 數(shù)是 100/2*16/2*2048/4*4 = 819,200 cycle。整個(gè) X*Y=Z 包括計(jì)算 128 個(gè)這樣的矩陣乘。所以總的 cycle 數(shù)是 819,200*128 = 104,857,600 cycles。在 1Ghz 的 C66 核上這相當(dāng)于104.8ms。但是我們的上述理論計(jì)算沒(méi)有考慮循環(huán)的前后綴消耗的 cycle 數(shù),也沒(méi)有考慮 cache miss stall 的等待時(shí)間。在 6678EVM 板的單個(gè) DSP 核上實(shí)測(cè),計(jì)算 X*Y=Z 消耗的實(shí)際時(shí)間是190,574,214 cycles。相當(dāng)于 190ms。
2.3.2 基于 OpenEM 的性能測(cè)試結(jié)果
基于 OpenEM的演示用例實(shí)現(xiàn)過(guò)程中,DSP 代碼中嵌入了少量測(cè)試代碼收集運(yùn)行的 cycle 信息。每個(gè)核把自己處理每個(gè) event 的起始和結(jié)束時(shí)間記錄在內(nèi)存(我們通過(guò)一個(gè)全局 timer 來(lái)保證所有DSP 核記錄的時(shí)間戳在時(shí)間軸上是同步的)。這些時(shí)間戳用 CCS 存到主機(jī)做后處理分析。通過(guò)分析,我們可以得到 8 個(gè) DSP 核并行處理消耗的時(shí)間。還可以分析每個(gè) DSP 核的忙/閑區(qū)間。
測(cè)試結(jié)果是,從第一個(gè) event 開(kāi)始處理到最后一個(gè) event 處理完,總時(shí)間是 31,433,438 cycle,也就是 31.4ms。也就是說(shuō),通過(guò) OpenEM把單 DSP 核的工作負(fù)載平衡到 8 個(gè) DSP 核上能達(dá)到的DSP 核利用率是 190,574,214/(31,433,438*8)= 76%。
通過(guò)對(duì)時(shí)間戳的處理我們得到下面的運(yùn)行圖,“-”表示 receiver 函數(shù)處理 event 的區(qū)間,本文稱之為有效時(shí)間。“#”表示 receiver 之外的區(qū)間(也就是代碼在 dispatcher 中執(zhí)行的區(qū)間),本文稱之為調(diào)度開(kāi)銷(xiāo)。每個(gè)“-”和“#”刻度表示 100,000 CPU cycle。
從上面的執(zhí)行圖看,調(diào)度開(kāi)銷(xiāo)不小,占了大約 15~20%的時(shí)間。但是這只是表面的現(xiàn)象。實(shí)際上,調(diào)度開(kāi)銷(xiāo)的大部分時(shí)間里,Dispatcher 是在查詢 hardware queue,等待新的 event。這是因?yàn)閜reload 沒(méi)能及時(shí)完成導(dǎo)致的。因?yàn)橥瑫r(shí)給 8 個(gè)核做 preload 需要很大的數(shù)據(jù)搬移的流量。根據(jù)以往的測(cè)試結(jié)果。使用 QMSS 的 packet DMA 從 DDR3 輸入數(shù)據(jù)到 local L2 的流量大約是 4G bytes 每秒。那么 preload 8 個(gè) event 總的數(shù)據(jù)量是 4byte * 2048 rows * 16 columns * 8 core = 1M bytes,需要的時(shí)間是 1/4 ms。因?yàn)槊總€(gè)“-”和“#”刻度表示 100,000 CPU cycle,運(yùn)行圖中紅線長(zhǎng)度就代表 preload 8 個(gè) event 的時(shí)間,它非常接近 250,000 cycle。理論計(jì)算和實(shí)際值基本吻合,所以我們認(rèn)為調(diào)度延遲是 packet DMA 的傳輸流量不足導(dǎo)致的。
我們也測(cè)試了不使用 pre-load 的場(chǎng)景。觀測(cè)到 scheduler 調(diào)度一個(gè) event 的延遲大約是 1200 個(gè)C66 CPU cycle。但是 DSP 核處理一個(gè) event 的耗時(shí)增大到原來(lái)的 10 倍。所以,pre-load 雖然會(huì)導(dǎo)致 QMSS packet DMA 流量不足成為凸顯的瓶頸,但是從總體效率來(lái)看還是非常必要的。
細(xì)心的讀者可能會(huì)發(fā)現(xiàn) 76% + 20% = 96%,并不是 100%。我們分析時(shí)間戳發(fā)現(xiàn),8 個(gè) DSP 核同時(shí)運(yùn)行的場(chǎng)景下,每個(gè)核處理一個(gè) 100*2048 × 2048*16 的矩陣乘的時(shí)間比只有一個(gè) DSP 核運(yùn)行的場(chǎng)景下的時(shí)間稍長(zhǎng)。原因是: 我們的演示用例中 X 矩陣和 Z 矩陣是存儲(chǔ)在 shared L2 的, 8 個(gè)核同時(shí)運(yùn)行就會(huì)同時(shí)讀寫(xiě)這兩個(gè) buffer,導(dǎo)致產(chǎn)生 shared L2 的 bank 沖突。 所以性能下降了。
3、總結(jié)
OpenEM具有使用簡(jiǎn)單,功能實(shí)用,執(zhí)行高效的特點(diǎn)。能在 KeyStone 多核 DSP 上實(shí)現(xiàn)動(dòng)態(tài)的負(fù)載平衡。它一方面提供了強(qiáng)大的功能,另一方面也給應(yīng)用留出了很大的靈活性。例如,通過(guò)讓?xiě)?yīng)用初始化 free pool 方便了 buffer 的管理。OpenEM 的現(xiàn)有功能已經(jīng)能夠支持基本的應(yīng)用。隨著版本更新功能還將不斷完善。
責(zé)任編輯:gt
-
處理器
+關(guān)注
關(guān)注
68文章
20256瀏覽量
252511 -
嵌入式
+關(guān)注
關(guān)注
5200文章
20458瀏覽量
334335 -
ti
+關(guān)注
關(guān)注
114文章
8069瀏覽量
219324
發(fā)布評(píng)論請(qǐng)先 登錄
34063的局限性
BGA封裝設(shè)計(jì)規(guī)則和局限性
基于微控制器的LED驅(qū)動(dòng)器拓?fù)洹?quán)衡和局限
OpenEM的原理簡(jiǎn)單的介紹和利用大矩陣乘的演示詳細(xì)介紹OpenEM的使用
ChatGPT的潛力和局限
藍(lán)牙與其他無(wú)線技術(shù)的比較:優(yōu)勢(shì)與局限
碳化硅二極管的優(yōu)點(diǎn)和局限性分析
超導(dǎo)材料在輸電領(lǐng)域的應(yīng)用前景、優(yōu)勢(shì)和局限性
WDM技術(shù)的缺點(diǎn)和局限性
在SMT貼片加工過(guò)程中“陰陽(yáng)板”的拼板設(shè)計(jì)有什么優(yōu)點(diǎn)和局限性
OpenEM的應(yīng)用原理、使用效率和局限的研究
評(píng)論