高速率AVS整数变换的汇编实现与优化
2012-01-27 11:21
197 查看
1 引言
AVS标准Ⅲ采用的8x8整数变换在获得较H.264更高的压缩率和主观图像质量的同时,增加了算法的实现复杂性和时间开销。本文重点研究AVS编解码器的整数变换模块,针对不同的算法实现模式,在原有Visual C++6.0整数变换模块基础上,分别应用MMX,SSE2和加强了乘法操作的SSE2内联汇编指令技术,优化整数变换的关键算法,实验结果表明,性能最优的SSE优化算法将单次整数变换的平均时延减少到0.5。ms以内,其编码速度比Visual C++6.0整数变换模块提高了6.3倍,实现了高速率的AVS整数变换,具有较大的实用价值。
2 AVS整数变换及蝶形算法
由于AVS正变换、反变换的基本原理近似,本文仅以正变换的分析与优化为例来详细说明。AVS对残差矩阵X的二维整数正变换定义为
式中:T8为变换矩阵,如图1所示。AVS整数变换的变换系数存在对称性,仅用加法和移位就可实现,消除了逆变换的不匹配,容易使用基8蝶形算法快速实现。图2所示为水平变换XT8的一维8点快速蝶形算法。显然,采用两个近似的C语言代码段就可实现由X到H的变换过程。依此设计的Visual C++6.O整数变换模块的算法清晰简单,容易更改数据长度,代码冗余少,但由于C程序不针对硬件编程,其较低的编解码速度不能满足HDTV实时性要求。
3 整数变换的优化设计
3.1 AVS整数变换的算法模式
利用矩阵乘法的结合律,公式(1)可以改写为
从而AVS整数变换的算法模式可分为4类:
1)水平变换一垂直变换:先水平变换H′=XT8再垂直变换
2)水平变换一转置一水平变换一转置:计算次序为
3)垂直变换一水平变换:计算次序为
4)垂直变换一转置一垂直变换一转置:计算次序为
无论采用上述哪种算法模式,为获得高质量主观图像效果并避免数据溢出,第一次变换前残差块X的每个元素均要由8位整型数据扩展为16位,第二次变换结果H的每个元素均要扩展为32位。为兼顾较高的图像压缩效率,最终输出结果需紧缩为16位的整型数据。
整数变换是典型的以计算为主的编码过程[2-3],为改进数字视频系统的实时性,需在Visual C++6.0基础上使用内联汇编,采用:Intel单指令多数据并行加速技术(SIMD)作面向硬件的程序流程和代码级优化[4]。
3.2基于MMX的优化
根据上面的分析,垂直变换比水平变换的汇编实现复杂很多,且转置过程中要并行处理多列数据,此时MMx指令集使用的64位寄存器遇到每次只能并行处理4个16位元素和2个32位元素的性能瓶颈,适合选择"水平变换一垂直变换"的算法模式:
1)水平变换H′=XT8:各矩阵元素均为16位,每次循环分两步处理残差矩阵X的一行元素,组合运算后得到矩阵H′相应行的元素,8次循环后计算得到矩阵H′。
2)垂直变换
:每次取矩阵H′的两列向量的前两个元素,扩展为32位数据后作组合运算,再将结果紧缩为16位数据;此过程分4次循环计算得到矩阵H。
图3为基于MMX的整数变换汇编优化的算法流程。程序中多次使用混排指令pshufw,节省了大量movq和punpckhdq指令的时间开销。
3.3基于SSE2的优化
SSE2是基于128位寄存器的指令集,并行处理能力强大,水平变换和矩阵转置比基于MMX的优化更易实现,采用"水平变换一转置一水平变换一转置"模式能仅以两次转置过程的延时为代价减少垂直变换的代码和时间开销。具体实现步骤:
1)第一次水平变换H′=XT8:各矩阵元素占一个字,每次变换一个行向量;
2)第一次矩阵转置得到H′;
3)第二次水平变换J=H′TT8:矩阵各元素占一个双字,每次取矩阵H′各列的前4个元素并扩展为32位数据,作一系列组合运算即每次对4个行向量水平变换,变换后结果紧缩为16位数据,只需2次循环就能变换完H′T的全部元素得到矩阵J;
4)第二次矩阵转置:采用与第一次矩阵转置相同的代码段得到H=JT。
根据图4所示的算法流程,编写的优化程序可使用大量相同的代码段实现第一次水平变换,而第二次水平变换仅用2次循环实现,2次转置由相同的混排程序实现,可见整个优化程序减少了循环调用和运算复杂度。
3.4侧重使用SSE2乘法指令的优化
研究表明,垂直变换是汇编代码开销最高、时间消耗最大的环节。根据增强乘法功能SSE2指令集能在多媒体处理中大量减少乘加运算的特点,图2和基于MMx的整数变换汇编程序中大量不可替换的乘加步骤可由侧重使用SSE2乘法指令进行优化。
假定矩阵
直接计算垂直变换
得到
观察公式(4)容易发现,一个元素hij需由H′的行向量与TT8的列向量共2个向量、16个元素计算得出,求H的任意一个行向量都须要8次重复调用H'的同一个行向量且分别调用矩阵TT8的8个列向量各一次。显然,乘加运算太多和寄存器资源有限使得这样的直接垂直变换编码的代码和冗余和时间开销代价非常大。
如果利用寄存器特性,公式(4)对日的行向量计算可由图5所示快速算法求出。图中每个方框代表一个128位的寄存器空间,每个寄存器存储8个16位数据,左右两边每对寄存器相同位置的数据对应相乘后结果相加,即得到所求矩阵H的行向量。这一算法大大减少了求和次数,而且乘积与求和可以循环运算,提高了寄存器的利用率。
4 优化效果
笔者分别使用MMx,SSE2并侧重使用SSE2乘法指令内联汇编,按照上文提出的优化算法在P4,1.8 GHz。512 Mbyte内存环境下进行了实验仿真,结果如表1所示。
仿真实验数据说明,基于SSE2的优化算法其单次AVS整数变换平均延时最短,降低到了0.5 ms以内,其编码速度是C程序的6.3倍和基于MMX优化算法编码速度的1.7倍,适合高端硬件实现并获得较高的性价比;基于MMX的优化算法延时稍长,但适于低端硬件实现获得较高的性价比;侧重使用SSE2乘法指令的优化算法的编码速度较基于MMX的优化算法优势不大,这是因为大量乘法指令的执行产生了超出算法分析的计算延时。
5 小结
AVS整数变换的延时对数字电视系统的实时性有着重要的影响。笔者针对AVS整数变换的不同实现模式进行了研究,结合MMX,SSE2和侧重使用乘法的SSE2等指令集的特性,在Visual C++6.0实现整数变换模块的基础上使用内联汇编,对整数变换模块进行了优化。实验结果表明,基于SSE2的整数变换优化算法的性能最优,单次变换的平均时延减至0.5 ms以内,实现了高速率的AVS整数变换,适合高端硬件实现并获得较高的性价比;基于MMX的优化算法适合低端硬件实现获得较高的性价比,而侧重使用SSE2乘法指令的优化算法也具有进一步研究的价值。
AVS标准Ⅲ采用的8x8整数变换在获得较H.264更高的压缩率和主观图像质量的同时,增加了算法的实现复杂性和时间开销。本文重点研究AVS编解码器的整数变换模块,针对不同的算法实现模式,在原有Visual C++6.0整数变换模块基础上,分别应用MMX,SSE2和加强了乘法操作的SSE2内联汇编指令技术,优化整数变换的关键算法,实验结果表明,性能最优的SSE优化算法将单次整数变换的平均时延减少到0.5。ms以内,其编码速度比Visual C++6.0整数变换模块提高了6.3倍,实现了高速率的AVS整数变换,具有较大的实用价值。
2 AVS整数变换及蝶形算法
由于AVS正变换、反变换的基本原理近似,本文仅以正变换的分析与优化为例来详细说明。AVS对残差矩阵X的二维整数正变换定义为
式中:T8为变换矩阵,如图1所示。AVS整数变换的变换系数存在对称性,仅用加法和移位就可实现,消除了逆变换的不匹配,容易使用基8蝶形算法快速实现。图2所示为水平变换XT8的一维8点快速蝶形算法。显然,采用两个近似的C语言代码段就可实现由X到H的变换过程。依此设计的Visual C++6.O整数变换模块的算法清晰简单,容易更改数据长度,代码冗余少,但由于C程序不针对硬件编程,其较低的编解码速度不能满足HDTV实时性要求。
3.1 AVS整数变换的算法模式
利用矩阵乘法的结合律,公式(1)可以改写为
从而AVS整数变换的算法模式可分为4类:
1)水平变换一垂直变换:先水平变换H′=XT8再垂直变换
2)水平变换一转置一水平变换一转置:计算次序为
3)垂直变换一水平变换:计算次序为
4)垂直变换一转置一垂直变换一转置:计算次序为
无论采用上述哪种算法模式,为获得高质量主观图像效果并避免数据溢出,第一次变换前残差块X的每个元素均要由8位整型数据扩展为16位,第二次变换结果H的每个元素均要扩展为32位。为兼顾较高的图像压缩效率,最终输出结果需紧缩为16位的整型数据。
整数变换是典型的以计算为主的编码过程[2-3],为改进数字视频系统的实时性,需在Visual C++6.0基础上使用内联汇编,采用:Intel单指令多数据并行加速技术(SIMD)作面向硬件的程序流程和代码级优化[4]。
3.2基于MMX的优化
根据上面的分析,垂直变换比水平变换的汇编实现复杂很多,且转置过程中要并行处理多列数据,此时MMx指令集使用的64位寄存器遇到每次只能并行处理4个16位元素和2个32位元素的性能瓶颈,适合选择"水平变换一垂直变换"的算法模式:
1)水平变换H′=XT8:各矩阵元素均为16位,每次循环分两步处理残差矩阵X的一行元素,组合运算后得到矩阵H′相应行的元素,8次循环后计算得到矩阵H′。
2)垂直变换
:每次取矩阵H′的两列向量的前两个元素,扩展为32位数据后作组合运算,再将结果紧缩为16位数据;此过程分4次循环计算得到矩阵H。
图3为基于MMX的整数变换汇编优化的算法流程。程序中多次使用混排指令pshufw,节省了大量movq和punpckhdq指令的时间开销。
3.3基于SSE2的优化
SSE2是基于128位寄存器的指令集,并行处理能力强大,水平变换和矩阵转置比基于MMX的优化更易实现,采用"水平变换一转置一水平变换一转置"模式能仅以两次转置过程的延时为代价减少垂直变换的代码和时间开销。具体实现步骤:
1)第一次水平变换H′=XT8:各矩阵元素占一个字,每次变换一个行向量;
2)第一次矩阵转置得到H′;
3)第二次水平变换J=H′TT8:矩阵各元素占一个双字,每次取矩阵H′各列的前4个元素并扩展为32位数据,作一系列组合运算即每次对4个行向量水平变换,变换后结果紧缩为16位数据,只需2次循环就能变换完H′T的全部元素得到矩阵J;
4)第二次矩阵转置:采用与第一次矩阵转置相同的代码段得到H=JT。
根据图4所示的算法流程,编写的优化程序可使用大量相同的代码段实现第一次水平变换,而第二次水平变换仅用2次循环实现,2次转置由相同的混排程序实现,可见整个优化程序减少了循环调用和运算复杂度。
研究表明,垂直变换是汇编代码开销最高、时间消耗最大的环节。根据增强乘法功能SSE2指令集能在多媒体处理中大量减少乘加运算的特点,图2和基于MMx的整数变换汇编程序中大量不可替换的乘加步骤可由侧重使用SSE2乘法指令进行优化。
假定矩阵
得到
观察公式(4)容易发现,一个元素hij需由H′的行向量与TT8的列向量共2个向量、16个元素计算得出,求H的任意一个行向量都须要8次重复调用H'的同一个行向量且分别调用矩阵TT8的8个列向量各一次。显然,乘加运算太多和寄存器资源有限使得这样的直接垂直变换编码的代码和冗余和时间开销代价非常大。
如果利用寄存器特性,公式(4)对日的行向量计算可由图5所示快速算法求出。图中每个方框代表一个128位的寄存器空间,每个寄存器存储8个16位数据,左右两边每对寄存器相同位置的数据对应相乘后结果相加,即得到所求矩阵H的行向量。这一算法大大减少了求和次数,而且乘积与求和可以循环运算,提高了寄存器的利用率。
笔者分别使用MMx,SSE2并侧重使用SSE2乘法指令内联汇编,按照上文提出的优化算法在P4,1.8 GHz。512 Mbyte内存环境下进行了实验仿真,结果如表1所示。
5 小结
AVS整数变换的延时对数字电视系统的实时性有着重要的影响。笔者针对AVS整数变换的不同实现模式进行了研究,结合MMX,SSE2和侧重使用乘法的SSE2等指令集的特性,在Visual C++6.0实现整数变换模块的基础上使用内联汇编,对整数变换模块进行了优化。实验结果表明,基于SSE2的整数变换优化算法的性能最优,单次变换的平均时延减至0.5 ms以内,实现了高速率的AVS整数变换,适合高端硬件实现并获得较高的性价比;基于MMX的优化算法适合低端硬件实现获得较高的性价比,而侧重使用SSE2乘法指令的优化算法也具有进一步研究的价值。
相关文章推荐
- 基于SIMD的AVS整数反变换算法设计与优化
- sw_scale中实现yuv420转rgb888——neon汇编优化
- AVS 帧内预测模式的汇编优化
- H.264中整数DCT变换,量化,反量化,反DCT究竟是如何实现的?(无代码,无真相)
- AVS游程解码、反扫描、反量化和反变换优化设计
- H.264中整数DCT变换,量化,反量化,反DCT究竟是如何实现的?(无代码,无真相)
- 编译器是如何实现32位整型的常量整数除法优化的?[C/C++]
- 找出满足a+b+c=n(n为正整数)的所有毕达哥拉斯元组(a,b,c)【python实现,时间复杂度优化】
- 【LintCode-463】整数排序(Java实现-冒泡排序优化)
- c语言:实现对于给定的正整数N,依次打印出小于等于N的所有素数。两种方法及其优化
- 汇编实现整数反向输出
- H.264中整数DCT变换,量化,反量化,反DCT究竟是如何实现的?
- 用C语言和汇编语言实现将1个整数分解成几个素数的乘积
- 在TI 的DSP 平台下优化AVS 的 IDCT 反变换的方法和代码
- SSE图像算法优化系列十一:使用FFT变换实现图像卷积。
- 分治法优化大整数乘法 C++实现
- 汇编怪谈——优化整数除法导致的灾难
- H.264中整数DCT变换,量化,反量化,反DCT究竟是如何实现的?
- c语言:实现对于给定的正整数N,依次打印出小于等于N的所有素数。两种方法及其优化
- 【H.264/AVC视频编解码技术详解】十五、H.264的变换编码(二):H.264整数变换和量化的实现