利用C和汇编语言混合编程实现DSP软件设计

时间:2012-08-29来源:网络

编译器内部函数(Compiler intrinsics):是指能够使用专门的宏或函数调用触发的内建编译器功能总称。没有内部函数支持的编译器必须调用用户定义的函数,这样做可能会令用户定义函数可能会在一个环路里产生函数调用和返回(见图4),从而产生巨大的开销。


图4:ETSI的mult_r(乘法和取整)基本操作的C代码实现(左)和对应的由CEVA-TeakLite-III编译器生成的汇编代码(右)。

汇编内部函数:是将汇编代码内联进C代码的一种先进方法,下文将有详细介绍。

把汇编指令当作C语句一样来编写

内联汇编功能具有显著的缺点。它会破坏各种编译器优化操作,因为编译器不了解内联代码的内容,会使用最坏假设;以及它可能迫使编程人员处理底层问题,如寄存器分配和指令调度。

汇编内部函数可以帮助编程人员实现内联汇编代码,并且不存在这些缺点。从编程人员的角度看,汇编内部函数就像是C语言宏或函数。它们接收C语言变量,返回C语言输出结果,同时表现为单个汇编指令。由于涉及该功能的所有代码都在C语言等级,因此编程人员不必担心寄存器分配、指令调度和其它底层问题。汇编内部函数不仅不会妨碍编译器优化操作,还会参与优化过程,就像它们是编译器正常产生的汇编指令一样。这些特征使得汇编内部函数的功能非常强大。

利用汇编内部函数,编程人员可以从编译器不可能产生的独特汇编指令中受益。例如,CEVA-X1641的bitrev(位反向)指令就是为FFT等算法定制的。由于编译器不太可能把一个程序看作一个FFT并使用bitrev指令,因此编程人员可以完全把bitrev汇编内部功能嵌入到C代码中。结合对应用的透彻了解,编程人员还可以使用C应用程序的性能决定段里的精确序列汇编内部函数,从而能够确保编译器生成的代码效率就像手工编写的一样高。

图5是CEVA-X1641编译器与汇编内部函数一起使用的例子。汇编内部函数还受益于由CEVA-X1641编译器处理的问题所决定的机器,如寄存器分配、指令调度和硬件单元分配。


图5:CEVA-X1641编译器支持的汇编内部函数的使用。

调试混合代码的应用程序

汇编代码的调试需要对延迟和存储器对齐限制等架构和机器级问题有深入的了解。只是简单地把C代码和汇编代码放在一起会使事情更麻烦,因为编程人员现在还必须调试C代码和汇编代码之间的连接。

调试混合代码应用程序的第一步就是分隔问题。假设保持汇编代码的C语言实现不变以及C语言实现方案工作正常,那么将汇编函数转换成C语言实现并重新测试应用程序就相对比较容易。为了迅速检测出问题,编程人员可以在每一步把受怀疑函数的一半转换为相应的C语言实现方案。

一旦有问题的汇编函数被确定,它就应该同时作为独立的汇编问题和C与汇编的连接问题加以分析。调试独立的汇编问题对汇编编程人员来说十分简单明了,但C与汇编的连接问题就有点麻烦。在考虑汇编函数本身时,C与汇编的连接问题是不可见的,这与独立的汇编问题有所不同。为了找出这些问题,编程人员必须检查编译器的约定,比如调用约定和寄存器使用约定。

编程人员还必须检查编译器假设,比如汇编指令的行踪。为了节省调试时间,编程人员应该在第一次实现汇编函数时验证是否遵循所有的编译器约定和假设。

案例研究:H.264视频编码器和AMR-NB

本文讨论的技术和方法已被CEVA公司用于各种各样的应用,包括视频编解码器、音频编解码器、声音合成器和设备驱动器。而本文所述的功能在这些应用中都可以显著提高性能。H.264视频编码器是一个很好的研究案例。它在处理能力及其它资源方面要求非常严格,尤其是相比语音编解码器等其它类型的编解码器而言。

CEVA公司的CEVA-X16xx高端DSP内核系列及其MM2000多媒体平台可以为这种编码器提供所需的处理能力。先用高级跟踪技术确定这种编码器的关键函数,然后逐步对之进行优化。首先,利用汇编内部函数在C语言级对这些函数进行全面优化。然后,在汇编语言级对编译器提供的汇编代码作进一步优化。

图6展示了通过对这种编码器的关键函数进行全面优化所获得的性能提高。只有最后一个优化阶段涉及到纯汇编编程,所有其它阶段都基于带有汇编内部函数的C代码。这些汇编内部函数主要用于SIMD操作,如avg_acW_acX_acZ_4b。这条指令对8个输入字节取平均,产生4字节结果。这种SIMD操作对执行大量字节级计算的视频编解码器非常有用。


图6:对H.264编码器的关键函数进行优化以提升性能。

1 2 3 4

关键词: DSP 汇编语言 混合编程 软件设计

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版