摘 要: 基于TI公司的多核DSP-TMS320C6678对黑白超声成像的中端(Mid-End)处理算法进行并行设计与实现。介绍了多核DSP编程实现算法所用到的关键技术:程序并行设计与第三代增强型直接内存存取(EDMA3),并重点分析了核间通信技术。根据算法的特点选用数据流模式对其进行了任务规划并分配到3个DSP核上执行,核间通信采用消息队列方案。实验结果证明了采用消息队列方案进行核间通信、实现多核并行的有效性。
关键词: 超声成像;多核DSP;核间通信;消息队列;EDMA3
当前,超声成像技术在临床诊断中得到了广泛的应用,随着技术的发展,对图像分辨率与成像实时性的要求越来越高[1],现有的单核DSP已经不能满足其信号处理需求。2010年,TI公司推出了采用KeyStone架构的TMS320C66x系列多核DSP。每个C66x核主频最高可达1.25 GHz,可实现每秒40 GMAC的定点运算或20 GFLOP的浮点运算;片内有4 MB的共享内存(MSMCSRAM),具有多种高速互联接口。并且,TI公司提供了具有任务调度、资源管理等功能的SYS/BIOS实时操作系统,可大大缩短开发周期。
本研究基于多核DSP-TMS320C6678对TI公司提供的黑白超声成像的中端(Mid-End)处理算法进行了并行设计与实现(前端的波束合成与数字解调一般在FPGA中完成[2]),以充分利用多核DSP的处理性能与C语言编程的灵活性。
文中介绍了多核DSP编程实现算法用到的3项关键技术:程序并行设计、核间通信和第三代增强型直接内存存取技术(EDMA3),着重对核间通信技术进行了分析,包括通知方案与消息队列方案。为高效地实现超声成像算法,首先对算法在单个DSP核上运行的性能进行了评估,然后根据算法各模块的时间消耗和数据依赖关系选择了数据流模式进行任务规划,分配到3个DSP核上执行。采用消息队列方案来实现各DSP核间的通知和同步,使用EDMA3实现外部存储器(DDR3)与共享内存之间的数据交换。
实验结果表明,超声成像处理算法在3个DSP核上运行的时间消耗为在单个DSP核上时间消耗的42%,DSP每秒钟可处理约40帧尺寸为512×1 024的图像,这表明多核DSP的并行处理能够满足超声成像的数据处理需求。实验结果证明了采用消息队列方案进行核间通信、实现多核并行的有效性。
2 多核DSP处理技术
为了实现TMS320C6678的多核处理,需要将算法分解为多个任务,分配到多个DSP核上并行执行。以下是实现过程中用到的几项关键技术。
2.1 程序并行设计
程序并行设计首先对应用进行任务规划,将一个应用分解为多个任务,然后根据一定的任务分配模式分配到相应的DSP核上执行[3]。多核程序开发中两种常用的任务分配模式如下。
(1)主从模式
主核作为控制核进行任务分配、调度和触发[4]。该模式适用于含有多个独立任务的应用。主核与从核间需要进行频繁地消息通信,从核之间不需要进行同步和数据传递。
(2)数据流模式
各DSP核以流水线的方式按照数据处理的流程执行各任务。该模式适用于分布式控制和数据处理的应用,这类应用中通常包含多个复杂的算法模块,单个DSP核不能满足需求,且各算法模块间有很强的数据依赖关系。
2.2 核间通信
TI公司提供了用于多核以及多核与外设之间通信的IPC库[5],其支持下列两种常用的通信方案。
(1)通知方案
通知方案(Notify)采用对目标核产生中断的方式实现DSP核间通信。其一次传递的数据为固定的32 bit,适合在多核间执行简单的同步操作。其配置方式如图2所示[5]。
通知模块(Notify Module)用于对通知方案中用到的资源进行静态配置。多核处理器模块(MultiProc Module)用于配置需要启用的DSP核个数及其名称。需要在SYS/BIOS操作系统的静态配置文件(*.cfg)中进行如下配置:
var Notify = xdc.useModule ('ti.sdo.ipc.Notify');
var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
var nameList =["CORE0", "CORE1","CORE2",……];
MultiProc.setConfig (null, nameList);
在程序中,Ipc_start()函数用于在各个DSP核之间建立连接;Notify_registerEvent()函数将每个DSP核使用的事件号与相应的回调函数对应起来;在DSP核执行过程中需要通知其他核执行相应操作时调用函数Notify_sendEvent(),该函数使用中断通知目标核执行与事件号对应的回调函数。
(2)消息队列方案
消息队列方案(MessageQ)通过在共享内存中开辟消息队列的方法实现DSP核间的通信,各DSP核通过轮询专属消息队列的方式来完成消息的获取,可以满足DSP核同步、核间数据传输等多种需求。该方案支持可变长数据的发送和接收;每个DSP核可拥有多个写消息端,即可同时向多个DSP核发送消息。其配置方式如图3所示。
消息队列模块(MessageQ Module)用于对消息队列方案中用到的资源进行静态配置。共享区模块(SharedRegion Module)用于开辟用来存放消息队列的共享区域。需要在SYS/BIOS操作系统的静态配置文件(*.cfg)中进行如下配置:
var MessageQ = xdc.useModule ('ti.sdo.ipc.MessageQ');
var Ipc = xdc.useModule ('ti.sdo.ipc.Ipc');
var MultiProc = xdc.useModule ('ti.sdo.utils.MultiProc');
var nameList = ["CORE0", "CORE1","CORE2",……];
MultiProc.setConfig (null, nameList);
var SharedRegion=xdc.useModule('ti.sdo.ipc.SharedRegion');
var SHAREDMEM = 0x0C000000;
var SHAREDMEMSIZE = 0x00200000;
SharedRegion.setEntryMeta(0,
{ base: SHAREDMEM,
len: SHAREDMEMSIZE,
ownerProcId: 0,
isValid: true,
name: "INTERNAL_SHARED_MEM",});
在主程序中,对MessageQ模块进行如下动态配置:
①使用Ipc_start()函数在各个DSP核间建立连接;
②使用MessageQ_create()创建本地消息队列;
③使用函数MessageQ_registerHeap()在消息队列与由SharedRegion模块开辟的共享区之间建立连接;
④使用函数MessageQ_open()打开由接收核创建的消息队列。
在程序执行过程中,对MessageQ模块中函数的调用流程如图4所示[5]。
DSP核发送消息时,使用函数MessageQ_alloc()在共享区分配消息空间,然后使用函数MessageQ_put()将消息发送到接收核的消息队列。当DSP核接收消息时,使用函数MessageQ_get()获取本地消息队列中的消息,然后调用函数MessageQ_free()或MessageQ_delete()删除该消息。通信完成后,调用MessageQ_close()关闭消息队列。
2.3 EDMA3
EDMA3是第三代增强型直接内存存取技术,支持一维(数组)传输、二维(数据帧)传输和三维(数据块)传输,这3种传输都可通过一次CPU触发(写入相应寄存器)或事件触发完成。
这里介绍实际使用的二维传输。数据帧中的每个元素为一个一维数组,可用于从大的数据块中等间隔地提取子帧。例如,可以将图像数据从逐行排列的外部存储器传输到内部缓冲区以实现隔行排列。为了实现二维传输,需要正确地配置参数RAM,其结构如图5所示。