0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OpenEM的应用原理、使用效率和局限的研究

电子设计 来源:网络整理 作者:佚名 2020-03-06 08:04 次阅读

1、OpenEM 简介

OpenEM 的全称是 Open Event Machine。它是 TI 开发的可应用于 Keystone 多核 DSP 的multicore runtime system library。OpenEM 的目的是在多核上有效的调度,分发任务,实现动态的负载平衡。基于 OpenEM,用户可以很容易的把原来的单核应用移植到 Keystone 多核芯片。需要注意的是 OpenEM 目前只能把任务调度分发到同一个 DSP 的多个核上,不能跨 DSP 调度分发。 OpenEM不依赖于 BIOS。它可以在芯片上裸跑,代码精简,效率高。而且,OpenEM不同于业界已经有 OpenMP 和 OpenCL 等开放式的 multi-core runtime systems。它是针对嵌入式系统的设计,更能满足嵌入式设计的实时性要求。TI 的 keystone 架构多核芯片中有 Multicore Navigator。它由 Queue Manager(简称为 QMSS)和一系列 Packet DMA engine 构成。OpenEM就是基于这套硬件系统构建的。例如,OpenEM 的 scheduler 是运行在 QMSS 的 PDSP(QMSS内部的 RISC 处理器)上的。OpenEM的 preload 功能是通过 QMSS 的 packet DMA 实现的。熟悉QMSS 的编程对学习 OpenEM 很有帮助。OpenEM 是 MCSDK 的一个组件。它还在不断的发展改进中。本文对 OpenEM 的介绍以及演示用例都是基于 BIOS MCSDK 2.01.02 的 OpenEM 1.0.0.2。

1.1 OpenEM 的软件对象

下面通过列表和图示介绍了 OpenEM的主要软件对象。表 1 是 OpenEM 的主要软件对象的列表。

需要注意的是,本文介绍的 OpenEM 的运行模式是:Scheduler 运行在 PDSP,Dispatcher 是“run to completion ”模式。

图 1 是一个软件对象关系图,显示出了表 1 中列举的软件对象。定义了 2 个 queue group,5 个queue 和 3 个 execution object。Queue group1 的 core mask 对应核 0 和 1。所以来自 queue1,2,3,4 的 event 只能在核 0 和核 1 上执行,因为这些 queue 属于 queue group1。Queue group2 的 core mask 对应核 2 和 3。所以来自 queue5 的 event 只能在核 2 和核 3 上执行,因为queue5 属于 queue group2。execution object 1 和 queue 1,2,3 映射关联。execution object 2 和queue 4 映射关联。execution object 3 和 queue 5 映射关联。图中的蓝线表示了 event 的行径,红线表示 command 的行径。图中的 SD queue 是 hardware queue,它不是一个软件对象而是OpenEM内部的组件。

1.2 OpenEM 的两个重要概念

OpenEM中有两个容易混淆的重要概念:prefetch 和 preload。

• Prefetch 是指每个 DSP 核向 scheduler 发命令,告诉 scheduler“本核已经空闲了,可以分配新的工作给本核了”。只有收到一个核的 prefetch 命令,scheduler 才会调度新的 event 给这个核。如果 DSP 核不发出 prefetch 命令,它就不会被分派任务。这是 OpenEM 的 scheduler的基本调度原则。

• Preload 和 event 的属性有关。通常,event 的数据是位于 DDR 的。如果 DSP 核直接访问DDR 效率会比较低。所以,OpenEM 可以把 event 的数据通过 QMSS 的 packet DMA 搬到DSP 核的 local L2。这个搬移的过程就是 preload。每个 event 的数据是否做 preload 是可配的。每个 event 在创建的时候都可以指定一个 preload 属性。Event 的 preload 属性可以是:

– Preload disable, 即不做预搬移

– Preload up to sizeA,即做预搬移,但是最多只搬 sizeA bytes

– Preload up to sizeB,即做预搬移,但是最多只搬 sizeB bytes

– Preload up to sizeC,即做预搬移,但是最多只搬 sizeC bytes

– 其中 SizeA,SizeB 和 SizeC 是常数,在 OpenEM 初始化的时候可以配置。

1. 3 OpenEM 的常用 API cycle 数

OpenEM的附带开销是应用最关注特性之一。所以我们实测了 OpenEM 常用 API 的 cycle 数如表2。需要注意的是:由于 OpenEM会负责 cache 一致性的维护,而有些 API 的处理过程中含有cache 一致性的维护操作。所以这些 API 的调用 cycle 数很大程度上取决于它对多大的数据缓冲区做了 cache 一致性的维护。本文测试这些 cycle 的场景使用的数据缓冲区的大小是是 4096 words(32bit)。

2、基于 OpenEM 的大矩阵乘实现

大矩阵相乘的目的是计算 X*Y = Z

矩阵 X 是(100 × 2048 )的浮点实数矩阵。

矩阵 Y 是(2048 × 2048 )的浮点实数矩阵。

矩阵 Z 是(100 × 2048 )的浮点实数矩阵。

由于矩阵 Y 的数据量很大,所以在多核 DSP 上可以把它拆分成多个子块,交给多个 DSP 核并行计算。如图 2 所示。

2.1 基于 OpenEM 的大矩阵乘方案设计

2.1.1 Memory 使用

Shannon DSP (6678)的内存系统包括片内的 LL2(local L2)和 SL2(shared L2)。加上片外的 DDR。LL2 的 size 是 512 Kbytes,每个核有一份 LL2。 SL2 的 size 是 4Mbytes,8 个核共享 SL2。DDR size 和硬件板卡设计有关,一般在 1G bytes 以上。 C66x 核对 LL2 的访问效率最高,对 SL2 的访问效率稍差,对 DDR 的访问效率最低。基于多种存储区间的不同特性,我们对数据存储位置按如下规划(参见图 3):

– 矩阵 X 的 size 是 800 Kbytes,存储是 shared L2

– 矩阵 Y 的 size 是 16 Mbytes,存储是 DDR

– 矩阵 Z 的 size 是 800 Kbytes,存储是 shared L2

虽然矩阵 Y 存储在 DDR,但是我们启用了 OpenEM 的 preload 功能。Preload 就是通过 QMSS 的 packet DMA 把待处理的 event 数据(通常位于 DDR)搬到被调度 core 的 LL2。所以 DSP 核运行的时候不直接从 DDR 取数。这保证了 DSP 核的数据访问效率。

2.1.2 处理流程

OpenEM中要有一个 DSP 核作为主核,其他核就是从核,主核要完成的工作较多。本文的演示用例中,核 0 是主核,核 1~7 是从核。主从核的分工差异如图 4:

1. 初始化 QMSS 和 free pool。

2. OpenEM 的 global 初始化和 local 初始化。global 初始化是主核执行。local 初始化是每个核各自执行。Local 初始化要等 global 初始化完成才能开始。所以,中间需要加一个barrier。Barrier 可以理解成一个同步点,所有 DSP 核在这个点完成一次同步再继续向下执行。本演示用例的 Barrier 是通过共享内存的软件信号量实现的。

3. 主核构造生产者/消费者场景并产生待处理的 event。生产者在 OpenEM 中不是一个软件对象。我们可以把产生 event 并发送到 queue 的函数认为是生产者。消费者就是 execution object,沟通生产者和消费者的管道就是 queue。构造生产者/消费者场景就是创建execution object 和 queue 并且把它们关联起来。

4. 主核和从核进入 event 处理的过程。

5. 主核检测到所有 event 都处理完成后为每个 DSP 核(包括它自己)产一个 exit job。

6. 主核和从核处理 exit job。从核直接调用 exit(0)退出。主核先做结果验证然后调用 exit(0)退出。

本文演示用例实现的几个特点是:

• OpenEM 的 free pool 是由用户初始化的。在初始化 free pool 的时候 event 描述符不指向数据缓冲区。等分配了一个 event 的时候再在这个 event 对应的描述符上挂数据缓冲区。这样可以避免不必要的数据拷贝(从 global buffer 拷贝到 event buffer)。

• 主核通过查询 free pool 中的 event 个数是否恢复回初始值来判断是否所有“矩阵乘 event”都处理。因为:

– Free pool 在初始化以后有 N 个 free event,

– 从中分配了若干个 event 后,free event 就减少了相应的个数,

– 每个 core 每处理完一个 event 就把这个 event 回收到 free pool,free pool 的 event 个数就加一。当 free pool 的 event 个数恢复回 N,就说明所有 event 都处理完了。

2.2 基于 OpenEM 的大矩阵乘实现

在初始化 OpenEM之前首先要做 multicore Navi

gator 的初始化。包括:PDSP firmware 的download, Link RAM 的初始化, Memory region 的初始化还有 free pool (也就是 free descriptorqueue)的初始化。这不属于本文介绍的范畴,本文直接介绍 OpenEM的初始化。

2.2.1 OpenEM 的 Global 初始化

OpenEM的 global 初始化通过调用 API 函数 ti_em_init_global()完成的。这个 API 的入参是下面所示的结构体。其中所列的参数是本文的演示用例使用的配置参数。本文针对每个参数的作用做了注释。了解了参数了含义,就能了解 OpenEM 的 global 初始化的大致做了些什么。

注释:

1. OpenEM要使用 hardware queue 资源。hw_queue_base_idx 用来指定 OpenEM 从哪个hardware queue 开始可用。

2. OpenEM 的少量操作需要多 DSP 核访问共享的数据结构。是通过 hardware semaphore 实现多核lock/unclock 的。所以通过 hw_sem_idx 告诉 OpenEM该使用哪一个 hardware semaphore。

3. 指定 preload 使用的 QMSS packet DMA 的通道的起始索引。QMSS packet DMA 有 32 个 RX/TX channel。在 OpenEM 中,每个 DSP core 要占用一个 TX/RX channel。

4. 指定 preload 使用的 QMSS Tx queues 的起始索引。要和 dma_idx 对应起来。QMSS 有 32 个 TX queue,索引是 800~831。对应 QMSS packet DMA 的 TX channel 0~31。所以,如果前面配置的 dma_idx 是 0,那么这里配置的 dma_queue_base_idx 应该是 800。

5. 指定 OpenEM local free pool 对应的 free queue index。Local free pool 是和 preload 相关的。local free pool 在物理上是一个 free descriptor queue。里面存储着 2 个 host 描述符。每个描述符对应一个 local L2 buffer。如果发生 preload,packet DMA 就从 free descriptor queue pop 描述符,然后把数据传到描述符指向的 local L2 buffer。每个 DSP 核有一个 local free pool。例如,在我们的演示用例中 core0~7 对应的 free descriptor queue 索引是 2050~2057。

6. 指定 OpenEM global free pool 的个数。每个 global free pool 包括 4 个初始化参数,例如{ globalFreePoolFdqIdx, TI_EM_COH_MODE_ON,TI_EM_BUF_MODE_GLOBAL_TIGHT,0}。参数 1是这个 global free pool 对应的 free queue index。接下来几项是这个 pool 中的 buffer 的属性。Global free pool 是用来从中分配 free event 的。调用 em_alloc()的入参之一就是 free pool index。

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。

2.3.2 基于 OpenEM 的性能测试结果

基于 OpenEM的演示用例实现过程中,DSP 代码中嵌入了少量测试代码收集运行的 cycle 信息。每个核把自己处理每个 event 的起始和结束时间记录在内存(我们通过一个全局 timer 来保证所有DSP 核记录的时间戳在时间轴上是同步的)。这些时间戳用 CCS 存到主机做后处理分析。通过分析,我们可以得到 8 个 DSP 核并行处理消耗的时间。还可以分析每个 DSP 核的忙/闲区间。

测试结果是,从第一个 event 开始处理到最后一个 event 处理完,总时间是 31,433,438 cycle,也就是 31.4ms。也就是说,通过 OpenEM把单 DSP 核的工作负载平衡到 8 个 DSP 核上能达到的DSP 核利用率是 190,574,214/(31,433,438*8)= 76%。

通过对时间戳的处理我们得到下面的运行图,“-”表示 receiver 函数处理 event 的区间,本文称之为有效时间。“#”表示 receiver 之外的区间(也就是代码在 dispatcher 中执行的区间),本文称之为调度开销。每个“-”和“#”刻度表示 100,000 CPU cycle。

从上面的执行图看,调度开销不小,占了大约 15~20%的时间。但是这只是表面的现象。实际上,调度开销的大部分时间里,Dispatcher 是在查询 hardware queue,等待新的 event。这是因为preload 没能及时完成导致的。因为同时给 8 个核做 preload 需要很大的数据搬移的流量。根据以往的测试结果。使用 QMSS 的 packet DMA 从 DDR3 输入数据到 local L2 的流量大约是 4G bytes 每秒。那么 preload 8 个 event 总的数据量是 4byte * 2048 rows * 16 columns * 8 core = 1M bytes,需要的时间是 1/4 ms。因为每个“-”和“#”刻度表示 100,000 CPU cycle,运行图中红线长度就代表 preload 8 个 event 的时间,它非常接近 250,000 cycle。理论计算和实际值基本吻合,所以我们认为调度延迟是 packet DMA 的传输流量不足导致的。

我们也测试了不使用 pre-load 的场景。观测到 scheduler 调度一个 event 的延迟大约是 1200 个C66 CPU cycle。但是 DSP 核处理一个 event 的耗时增大到原来的 10 倍。所以,pre-load 虽然会导致 QMSS packet DMA 流量不足成为凸显的瓶颈,但是从总体效率来看还是非常必要的。

细心的读者可能会发现 76% + 20% = 96%,并不是 100%。我们分析时间戳发现,8 个 DSP 核同时运行的场景下,每个核处理一个 100*2048 × 2048*16 的矩阵乘的时间比只有一个 DSP 核运行的场景下的时间稍长。原因是: 我们的演示用例中 X 矩阵和 Z 矩阵是存储在 shared L2 的, 8 个核同时运行就会同时读写这两个 buffer,导致产生 shared L2 的 bank 冲突。 所以性能下降了。

3、总结

OpenEM具有使用简单,功能实用,执行高效的特点。能在 KeyStone 多核 DSP 上实现动态的负载平衡。它一方面提供了强大的功能,另一方面也给应用留出了很大的灵活性。例如,通过让应用初始化 free pool 方便了 buffer 的管理。OpenEM 的现有功能已经能够支持基本的应用。随着版本更新功能还将不断完善。

责任编辑:gt


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    19273

    浏览量

    229715
  • 嵌入式
    +关注

    关注

    5082

    文章

    19115

    浏览量

    304914
  • ti
    ti
    +关注

    关注

    112

    文章

    8065

    浏览量

    212378
收藏 人收藏

    评论

    相关推荐

    重采样的作用和局限

    滤波器算法
    皮特派
    发布于 :2022年08月01日 15:11:00

    34063的局限

    由34063构成的开关电源虽然价格便宜、应用广泛,但它的局限性也是显而易见的。主要有以下几点:(1)效率偏低。对于降压应用,效率一般只有70%左右,输出电压低时效率更低。这就使它不能用
    发表于 06-12 10:41

    FreeRTOS使用笔记和局部注释翻译

    FreeRTOS使用笔记和局部注释翻译
    发表于 09-18 08:02

    BGA封装设计规则和局限

    160至225条I/O引线的0.05英寸间距封装中,没有缺陷产生。而其它的全自动工厂中,具有相同I/O引线数的细间距器件的失效率为500或1000PPM。目前正在进一步开发具有400到700条I/O引线
    发表于 09-05 16:37

    多核嵌入式系统存在的局限性?怎么解决这些问题?

    本文列举了多核嵌入式系统存在的一些主要局限,并对解决这些局限的可行方案进行了探讨。将以一些嵌入式系统为例,指出利用现有架构改进系统节能效果的机遇。多核处理器与新兴的嵌入式平台的结合能够满足现代嵌入式
    发表于 03-09 06:36

    OpenEM的原理及使用方法

    OpenEM 简介和基于 OpenEM 的大矩阵乘实现
    发表于 04-02 06:19

    栅漏电流噪声有哪几种模型?这几种模型具有什么特性和局限性?

    栅漏电流噪声特性是什么?栅漏电流噪声有哪几种模型?这几种模型具有什么特性和局限性?
    发表于 04-14 06:53

    Web服务结构模型的研究与实现

    分析了传统的分布式计算模式在Internet应用上的不足和局限性,阐述了Web服务的特点和优势。研究了Web服务机制的原理和体系规范。以一个图档管理应用为例,介绍了使用Apache A
    发表于 08-10 08:42 5次下载

    基于微控制器的LED驱动器拓扑、权衡和局限

    本文主要探讨基于微控制器的LED驱动器。它考察了以微控制器作为系统核心所能采用的各种不同拓扑结构。它还详细讨论了各种拓扑的权衡,着重于它们的主要特性和局限:通讯、电压
    发表于 10-26 14:17 909次阅读
    基于微控制器的LED驱动器拓扑、权衡<b class='flag-5'>和局限</b>

    OpenEM的原理简单的介绍和利用大矩阵乘的演示详细介绍OpenEM的使用

    本文首先对OpenEM的原理做了简单的介绍。然后结合一个大矩阵乘的演示用例详细介绍了OpenEM的使用。最后通过量化分析这个演示用例的执行cycle 数,总结了OpenEM效率
    发表于 04-28 10:02 5次下载
    <b class='flag-5'>OpenEM</b>的原理简单的介绍和利用大矩阵乘的演示详细介绍<b class='flag-5'>OpenEM</b>的使用

    ChatGPT的潜力和局限

      今天为大家分享一篇研究,当ChatGPT穿越到口袋妖怪世界,是否会理解并应用这个虚构世界的知识呢?   熟悉口袋妖怪的朋友们一定知道,这些可爱的生物们有着各种不同的属性、类别和技能。它们生活
    的头像 发表于 06-13 17:23 574次阅读
    ChatGPT的潜力<b class='flag-5'>和局限</b>

    蓝牙与其他无线技术的比较:优势与局限

    在无线技术的世界中,蓝牙技术因其独特的特性和广泛的应用而脱颖而出。然而,像所有技术一样,蓝牙也有其优势和局限性,特别是当与其他无线技术如Wi-Fi、Zigbee和NFC等进行比较时。本文旨在探讨这些
    的头像 发表于 12-14 16:18 831次阅读

    碳化硅二极管的优点和局限性分析

    碳化硅二极管的优点和局限性分析 碳化硅(SiC)二极管是一种新型半导体材料,在高频电源电子装置中得到了广泛应用。与传统的硅(Si)材料相比,碳化硅二极管具有许多优点和局限性。下面是对碳化硅二极管
    的头像 发表于 12-21 11:31 2573次阅读

    超导材料在输电领域的应用前景、优势和局限

    超导材料适合作为输电导线的潜力一直备受瞩目。与传统的金属材料相比,超导材料具有低电阻和高电流载流能力的独特优势。本文将深入探讨超导材料在输电领域的应用前景、优势和局限性。 在高科技时代,全球对电能
    的头像 发表于 01-17 11:29 1548次阅读

    WDM技术的缺点和局限

    效率。然而,尽管WDM技术具有诸多优势,但它也存在一些缺点和局限性。以下是对WDM技术缺点和局限性的详细分析:
    的头像 发表于 08-09 11:42 768次阅读