对于系统运行最耗时的循环体,采取适当改写循环形式、多重循环体展开等方法有效地减少运算的复杂度。此外,减少调用函数次数,改写if-else语句也是有效的优化手段。
www.55dianzi.com
3.2.2 去除参考代码中的大量冗余代码和重复计算
a) 因为使用的参考代码是JM8.6中的去方块滤波模块,该模块可以对H.264的各种挡次和级别的码流进行滤波,而解码器是基于基本挡次的,仅仅涉及到I帧、P帧的滤波操作,因此可以将参考代码中的关于B帧、SP/SI帧、场模式和帧场自适应模式的相关滤波部分去除。
繁调用片外数据的时间,提高了运行速度;另一方面通过对待滤波宏块的细分,减少了参考代码中的判断引起的流水线中断,也在一定程度上提升了程序速度。
3.3 汇编级别的优化
BlackfinBF533 处理器 的内核支持C或C++语言,但由系统自动将C程序翻译成汇编语言效率比较低下,因此对一些系统调用比较频繁、耗时较多的模块,可以用人工将其转化成高效率的汇编语言来提高运行速度。主要通过以下几个方面来提高程序的速度:
a) 以寄存器变量代替局部变量。在C语言中,子程序和函数中往往使用局部变量来暂时存放数据。当程序运行时,编译器为声明的所有局部变量开辟临时内存空间,对于局部变量的存取操作都涉及到内存的存取,而内存访问的速度相对于寄存器访问是很慢的。因此,可以利用系统中的数据寄存器、指针寄存器来替代仅仅起暂存作用的局部变量,从而大大节省系统访问内存带来的时间延迟。但由于系统中的寄存器数量对于局部变量来说相当有限,因此必须合理高效地使用寄存器。
b) 以硬件循环代替软件循环。软件循环是指在for或while等循环的开始或结尾处设置判断条件来控制循环的开始、继续、结束。软件循环的条件判断指令会动态地选择分支,一旦发生跳转,会阻塞流水线,而保持流水线的畅通是保持高效运行的关键因素。Blackfin处理器有专用的硬件支持两级嵌套的零开销硬件循环,这种方式不需要判断条件转移,DSP硬件根据预定的循环次数自动执行循环并结束循环,从而保证了流水线的畅通,提高速度。
c) 充分利用数据总线宽度。Blackfin533外部数据总线宽度32位,一次可存取4字节。因此,充分利用数据总访问宽度,特别在操作大量数据时,保持一次存取4字节,可减少指令周期数,从而提高执行速度。
d) 高效使用并行指令和向量指令。并行指令和向量指令是Blackfin系列DSP的一大特点。通过对并行指令的使用,可以充分发挥Blackfin处理器的SIMD系统结构的优点及硬件资源的并行处理能力,减少指令数,从而提高程序执行效率。往往通过对程序的合理安排可以做到使用1条并行指令来替代2条或3条非并行指令。向量指令则充分利用指令宽度,同时对多个数据流进行相同操作,如要进行2个16位的算术或移位操作,完全可以通过1个32位的向量指令来实现,从而以1个时钟周期来实现原来2个周期的工作。例如R3=abs R1(V)就用1个指令周期同时实现2个16位数据的求绝对值操作。
e) 合理配置数据存储空间。限于DSP片内和片外数据存储空间的访问速度和容量特点,片内空间存取速度快但容量很小,而片外空间较大但访问速度慢,因此,合理地分配数据存放位置对于提高程序的运行速度是十分关键的。对于使用频率高的数据尽量放在片内空间中,而不常用的数据放在片外空间中。若要存取位于片外的数据时,应将待存取的数据尽量安排成连续分布,一次将大块的片外数据读进片内缓存,避免频繁读取片外数据带来的时间浪费。
4 优化实现的结果
测试优化效果的方法是将参考代码JM8.6中的去方块滤波C程序模块加到原有的解码器中进行测试,并与经过系统、算法、汇编3个级别优化的去方块滤波汇编程序模块的测试周期进行对比。选择的测试图像序列为Clarie.cif、Paris.cif、Mobile.cif,测试数据见表1。
由表1可以看出,与未优化前的JM8.6中的C程序代码相比,经过优化后的去方块滤波汇编模块效率提高了7倍左右。
5 结束语
本文通过系统、算法及汇编3个级别优化实现了H.264中的去方块滤波功能,特别是通过改进去方块滤波的实现算法,对待滤波的宏块进行分类以及充分地利用并行指令、向量指令等汇编级别的优化手段,取得了较好的优化效果。优化实现的去方块滤波模块,基于原有的H.264解码器上对一个25帧约400 kbit/s的图像序列进行滤波,大概需要250 MHz的时钟周期,而解码器的总周期约为700 MHz的时钟周期,从而使得解码器的解码速度达到约20帧/s,基本达到准实时解码的要求。
该实现方法相对于参考模块进行了较好的优化,但通过对程序进行耗时分析,在读取待滤波数据和重新写入已滤波的数据,获取BS值的GetBs函数和进行滤波的EdgeLoop函数方面都还有进一步提升的空间。对于片外片内数据的交互可以采用DMA技术,在滤波的同时进行数据读写,从而抵消数据搬移消耗的时钟周期;对于GetBs和EdgeLoop中的汇编代码实现效率还有进一步改进的空间;这两方面也是下一步的改进方向。