用C语言进行DSP软件设计的优化考虑武汉力源电子股份有限公司技术开发部(430010)刘朝晖摘要讨论了用C语言进行DSP软件设计中常用的一些优化策略。关键词C语言DSP优化TMS320C54x1前言与单片机相比,DSP多用于算法比较复杂、乘加运算量比较大的场合,如通信、雷达、音视频处理等。为了追求代码的高效,过去一般用汇编语言来编制DSP的应用软件。随着技术的发展,DSP的应用范围不断延伸,且日趋复杂,而单纯的汇编语言程序的可读性、可修改性和可重用性太差,软件需求与软件生产力之间的矛盾日益突出,高级语言(如C语言)的引入,有望解决这一矛盾。与此同时DSP的运算速度大幅度提高,以DSP为平台的C编译器的功能不断完善,这也为C语言的采用提供了可能。DSP的运算能力差别很大,以TI公司的DSP产品为例,TMS320C64x的运算能力已达4800~8800MIPS,而低端DSP产品的运算能力一般为20~40MIPS。价格上也是天渊之别,从数千元到几十元。涉及到具体应用时,器件的选择要遵循一个合适的性价比。一般而言DSP的运算能力越强,其价格相对较贵。为此软件的实时性不能完全依赖于器件运算性能的无限提升。特别是当采用C语言进行DSP软件设计时,其效率一般比用汇编语言编制的要低,因此,优化工作更为必要。鉴于DSP应用的复杂性,在用C语言进行DSP软件开发时,一般先在PC机或工作站上对算法进行仿真,仿真通过后再将C程序移植到DSP平台中。按照开发的顺序,相应的优化工作也包括两部分:一是仿真环境中的优化,二是DSP目标环境中的进一步优化。下面结合TI公司的TMS320C54x系列DSP的C编译器,具体讨论相关的优化工作。2仿真环境中的优化PC机环境中的优化工作是针对C程序的通用特性来考虑的。这方面的优化工作主要包括采用快速算法、计算表格化、数组指针化和尽可能减少判断转移。2.1快速算法与直接算法相比,快速算法通常放弃了概念上的清晰度,而追求计算上的高效率,最典型的例子就是DFT与FFT。DCT(离散余弦变换)是另一种常用的正交变换,以一个直接的32×32的DCT变换为例,共需做1024次乘法和992次加法。而采用了Lee提出的快速DCT变换方法后,对于同样的输入条件,只需做384次乘法和432次加法。当然,快速算法的采用增加了数据移动的工作量,这也是许多DSP都支持FFT中特殊的位反转寻址的原因。因而在采用快速算法时,通常需要在运算量的减少和数据移动的增多之间作一个折中。总之,适当地采用快速算法,是进行DSP应用软件优化时首先要考虑的问题。2.2计算表格化为了提高算法的实现效率,减少运行时计算的时间开销,应尽可能把一些运行时计算的参数做成查找表或常数数值,从而将运行时的计算转化为编译时的计算。这不仅适用于一些比较规整的参数表,对于一些并不规整的运行时计算,特别是比较耗时的计算(如浮点除),也应尽量使之表格化。2.3数组指针化在C语言程序中,对数组的寻址是非常耗时的,特别是对多维数组。因此,首先应降低数组的维数,再进一步使之指针化。程序1是未经优化的C程序,它对输入数组in[32]进行蝶型变换,得到两个输出数组even[16]和odd[16]。将数组指针化后,得到程序2中的优化代码。程序1:采用数组的C程序voidBufferfly(short*in){shorteven[16],odd[16];shorti;for(i=0;i16;i++){even[i]=in[i]+in[31-i];odd[i]=in[i]-in[31-i];}}程序2:采用指针的C程序voidBufferfly(short*in){shorteven[16],odd[16];short*in_ptr,*even_ptr,*odd_ptr;shorti;in_high_ptr=&in[31];even_ptr=even;odd_ptr=odd;for(i=0;i16;i++){*even_ptr++=(*in)+(*in_high_ptr);*odd_ptr++=(*in++)-(*in_high_ptr--);}}显然,采用数组的C程序表达清晰,可读性好,但效率很差。与之相反,采用指针的C程序不用计算指针地址,只需将指针增量,配合DSP中寻址机构所支持的增量寻址,效率大为提高,但可读性却降低了。2.4减少判断转移DSP多采用流水线结构如TMS320C54x中就采用了6级流水线结构,频繁的转移指令将使流水线难以发挥作用。另外DSP的大多数指令为单周期指令,但转移类指令却通常要耗费较多的机器周期。因此,应尽可能减少程序中的转移分支。事实上,通过对程序流的分析,许多判断转移可以用简单的条件组合来实现。例如程序3中的用于溢出处理的C代码,逻辑上可以等效为程序4中的代码。程序3:采用判断转移的C程序if(sum32767)sum=32767;if(sum-32768)sum=-32768;程序4:进行逻辑优化的C程序sum=min(sum,32767);sum=max(sum,-32768);另一种常用的减少判断转移的方法是将循环展开。特别是对多重循环控制,若外层循环次数较少,可将内层循环直排,从而减少对外层循环次数进行控制转移的时间。3DSP环境中的进一步优化以上讨论了在仿真环境中涉及到的一些优化工作。当C程序向目标DSP平台移植时,还需结合DSP器件特点,作一些特殊的优化考虑,主要包括两方面,一是如何合理地安排存储空间,二是如何有选择地做一些手工汇编的调整。3.1存储空间重排根据器件型号和系统配置的不同,一个DSP系统的存储空间配置可谓千差万别,而DSP对不同存储单元的访问速度是有区别的,其中对片内寄存器的访问速度最快,对片内RAM的访问速度比对片外RAM的访问速度快。因此,合理地配置和使用存储空间,对系统整体效率影响很大。一般应尽量将访问比较频繁的常数表和代码段装入片内RAM。而片内RAM一般又比较有限,若常数表过多,则应考虑将其分段装入片内或片外的存储器。当采用一些特殊寻址方式时,往往也需要考虑存储空间的重排。如环型缓冲区管理,以TMS320C54x为例,若缓冲区长度为1024,则该块缓冲区需从xxxx,x000,0000,0000处开始。与此相应,其它的存储空间就需进行调整。3.2局部手工汇编经过上述优化的C代码的效率将大为提高。但若实时性仍不能满足,可进一步作手工汇编的调整,并且应该保持原有C代码的可读性。因此,应尽可能选择对效率提高明显的C代码段进行手工汇编的调整。1.块重复和单指令重复在DSP应用中,往往存在大量的重复处理。因此,多数DSP从硬件上提供对重复操作的支持,包括单指令重复和块重复,如TMS320C54x提供有RPT和RPTB两条指令,分别支持这两种重复的零开销控制。2.特殊寻址方式DSP要处理的数据较为复杂,但在数据组织上一般存在一定的规律。为此DSP的地址产生机制支持丰富的寻址方式,如自动增/减等。在实际应用中常常需要对一片缓冲区进行环形处理,即处理完尾数据后再从头数据继续处理。如果采用普通的处理方法,那么每次寻址时都需用软件将所寻地址与尾地址进行比较,若超出范围,则寻址至头地址。这样是非常耗时的。为此,许多DSP都从硬件上支持对环形缓冲区的管理。为了使用该功能,需要将环形缓冲区分配到相对特定的存储空间。即使是带优化功能的C编译器,也很难做到这一点。而采用嵌入汇编实现环型缓冲区的硬件管理,将使相关代码效率得到极大的提高。3.延迟转移在任何处理器中,转移指令都是很耗时的。如果在执行多周期的转移指令的同时,能够执行下一条指令,那么,若判定条件为真,将使得转移指令的周期数减少,这就是延迟转移的含义。以TMS320C54x为例,如果一条转移指令(B指令)需要4个机器周期,后面为一条2周期指令,顺序执行完这两条指令需要6个机器周期;若改用延迟转移指令(B指令),则4个机器周期即可执行完这两条指令,从而使延迟转移指令等效为一条2周期指令。4.并行指令在TMS320C54x中,有两组数据读总线,一组数据写总线。为此,可以考虑采用并行指令在一个周期内完成对2个数据单元的操作。例如,在一个周期内将累加器A的内容存至一个存储单元,并将另一个存储单元的内容装入累加器A,该操作可用并行指令表示如下:STA,*AR3+||LDAR2+,A5.减少函数调用对程序3中的代码作简单处理后,程序4中的代码由于要作C库函数的调用,其效率并未提高,甚至更差。但如果可以利用DSP中一些高效的汇编指令,不仅代码的效率大幅提高,而且也非常简洁。以TMS320C54x的汇编指令集为例,其中有MIN和MAX两条单周期指令,分别实现两个数中的取小和取大。若在代码移植过程中采用嵌入汇编,可以将程序4的例子改写成程序5中的汇编码。其中,sum已存入累加器A中。程序5:嵌入汇编程序asm(LD#32767,B);asm(MINB);asm(LD#-32768,B);asm(MAXB);6.使用寄存器在所有的存储器中,DSP对片内寄存器的存取速度是最快的,为此,尽可能提高宝贵的片内寄存器的利用率是非常重要的。一方面可以将系统尚未用到的特殊寄存器分配给一些使用频率特别高的变量。另一方面在遵循C编译器规则的前提下,可进一步提高通用寄存器的使用率,因为通用寄存器往往支持更为丰富的寻址和特殊操作。以TMS320C54x为例,共有8个通用寄存器,C编译器一般将AR1用作局部变量暂存,将AR7用作全局变量。可以在C程序里声明寄存器变量(最多2个),也可以考察编译所产生的汇编码,直接使用尚未被编译器用到的AR6或AR7。4结束语以上探讨了用C语言开发DSP软件时需要进行的一些优化考虑。作为通用DSP的全球最大供应商,TI公司在近两年来也着重强调了在软件和应用方案方面的支持。随着实时操作系统、可视开发环境的引入,DSP的应用将更为便捷。参考文献1.TMS320C54xOptimizingCCompilerUser’sGuide.TI,19972.TMS320C54xAssemblyLanguageToolsUser’sGuide.TI,19973.TMS320C54xDSPCPUandPeripherals.TI,19964.TMS320C54xDSPMnemonicInstructionSet.TI,1996(收稿日期:2000-11-02)