一种龙芯平台上多媒体指令优化时地址非对齐问题的解决方案

2021-02-04 13:51李正平程洋洋
小型微型计算机系统 2021年1期
关键词:测试用例龙芯指令

李正平,程洋洋

(安徽大学 电子信息工程学院, 合肥 230039)

1 引 言

现代计算机中内存空间都是按照byte划分的,对于内存中的基本数据类型的变量,如果它们的起始地址能够被其自身的大小整除,则将该变量称为自然对齐数据,反之称为非对齐数据[1].

不同硬件平台在非对齐数据的处理方面存在很大差异[2].如以MIPS和ARM为代表的精简指令集计算机对地址要求较为严格,需要地址自然对齐;而以X86为代表的复杂指令集计算机就不需要.通常来说,若不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失.比如在MIPS平台上,如果一个int型数据(假设为32位系统)存放在4的整数倍的地址上,那么一个读周期就可以读出;而如果存放在非4的整数倍的地址上,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int型数据,这显然会在存取效率上下降很多[3].在龙芯平台多媒体指令优化时,优化函数一旦访问非对齐数据会严重抵销优化函数的性能提升,影响程序的执行效率.因此,保证优化函数在数据非对齐时也能有较高的性能是一个需要解决的问题.

针对非对齐数据存在的问题,许多学者进行了大量研究,提出了许多行之有效的解决方案.其中,IBM公司的Eichenberger A E[4]提出了一种在内存非对齐的情况下对循环进行矢量化处理的方案,即自动重组寄存器中的数据,以满足硬件提出的对齐要求;浪潮(北京)电子信息产业有限公司[5]在初始化时就把非对齐地址根据映射表中记录的偏移量纠正为对齐地址,这样上层应用看到的就全是对齐地址.以上介绍的是基于软件层面的解决方案,国防科学技术大学余成龙[6]从硬件上对高性能应用程序的访存结构进行建模,设计并实现SIMD分离缓冲行非对齐访存结构与双体cache非对齐访存结构来提高访存性能等.

以上所提到的方法在非对齐访存问题上都有一定的效果和意义[7],解决方法是由问题决定的,都服务于各种针对性的问题,本身无优劣之分.因此,具体问题还要具体分析[8].针对在龙芯平台上多媒体指令优化过程中遇到的非对齐访存造成优化函数性能下降的问题,本文提出了接口自适应择优算法.该算法在软件层面上利用龙芯平台在指令集层面上设计的非对齐存取指令,先为这些指令设计非对齐访存接口,并在源代码中根据程序上下文环境选择合适的非对齐访存接口去存取数据.最后,以LibYUV库的多媒体指令优化结果验证了所提算法在数据非对齐的情况下依旧有较高的性能.

2 龙芯多媒体指令优化中非对齐访存问题

龙芯多媒体指令是一套支持基于字节、半字、字以及双字整数并行操作的指令集,能够加速多媒体运算.龙芯多媒体指令直接使用FPU 的浮点寄存器(64 位,32 个)作为多媒体指令寄存器来实现整数的并行操作,因此通常用存取浮点类型数据的指令来存取需并行计算的整数[9].

浮点包括单精度和双精度两种类型,分别使用4个和8个字节表示.在龙芯平台下分别使用lwc1/swc1、ldc1/sdc1(浮点存取指令)来存取浮点类型数据,其中 lwc1/swc1要求目标数据必须是4字节对齐,ldc1/sdc1要求目标数据是8字节对齐.大多数情况下,数据也确实是按照上述一样对齐的.但有时可能会错误的使用ldc1/sdc1来存取4字节对齐的浮点数据,有时甚至传递进函数处理的多媒体数据流就是非对齐的,这样硬件会抛出异常,程序会中断执行;通过操作系统内核响应alignment fault异常进入异常处理流程中,把对非对齐的数据访问操作转换为通过多次访存操作和拼接操作的过程.这个过程由于上下文切换以及引入的多次访存和拼接操作必然大幅影响程序的执行效率[10].

图1 gslwrc1/gslwlc1指令的数据加载过程Fig.1 Data loading process of gslwrc1 / gslwlc1 instruction

对于以上问题,龙芯自定义通用指令gslwrc1/gslwlc1、gsswrc1/gsswlc1、gsldrc1/gsldlc1、gssdrc1/gssdlc1分别在地址非对齐的情况下存取需并行操作的数据.其中gslwrc1/gslwlc1表示从非对齐的内存地址空间中取字的最低/最高有效部分存放到浮点寄存器中,gsswrc1/gsswlc1表示存储浮点寄存器中字的低/高有效部分到非对齐的内存地址空间.gsldrc1/gsldlc1作用同gslwrc1/gslwlc1,gssdrc1/gssdlc1作用同gsswrc1/gsswlc1,只是操作的目标数据是双字.

现以gslwrc1/gslwlc1指令为例对非对齐访存指令的数据加载过程做出说明.Gslwlc1指令用以从非对齐的内存地址空间中取字W的最高有效部分存放到浮点寄存器中,这个地址在内存中是以任意字节为边界开始的.浮点寄存器$f0中字的最低有效部分(右)则维持不变,浮点寄存器$f0的63..32位是不确定的;同理,gslwrc1指令用以从非对齐的内存地址空间中取字的最低有效部分存放到浮点寄存器中,两条指令结合使用才能完成从一个非对齐地址读取一个字数据.如图1所示,gslwlc1在这种情况下只加载一个字W的最高字节到浮点寄存器$f0中,字W的余下低3个字节则由gslwrc1完成加载.

3 非对齐访存接口和接口自适应择优算法

龙芯下现有的访存接口名称分别为:_mm_load_si64、_mm_store_si64、_mm_load_si32和_mm_store_si32.其中,_mm_store_si64的接口实现如下:

extern __inline void FUNCTION_ATTRIBS

_mm_store_si64(__m64 *dest,__m64 src)

{

asm("sdc1 %1,%0 "

:"=m" (*dest)

:"f" (src)

:"memory"

);

}

使用龙芯多媒体指令技术进行函数优化时,需要函数参数地址是自然对齐的,使用现有访存接口即可完成数据的加载和储存操作.但有时候会出现多媒体指令优化后函数性能不提升反而下降的情况,这一般跟函数访问了非对齐地址有关.为了解决这个问题,我们设计了新的访存接口.

3.1 非对齐访存接口

对于确定为非对齐的参数地址,利用龙芯非对齐访存指令,本文分别定义了32位/64位的非对齐访存接口,用以在多媒体指令优化时地址非对齐的时候使用,非对齐访存接口名称分别为:_mm_loadu_si64、_mm_storeu_si64、_mm_loadu_si32和_mm_storeu_si32.其中,_mm_storeu_si64接口实现如下:

extern __inline void FUNCTION_ATTRIBS

_mm_storeu_si64(__m64 *dest,__m64 src)

{

asm("gssdlc1 %1,7+%0 "

"gssdrc1 %1,%0 "

:"=m" (*dest)

:"f" (src)

:"memory"

);

}

非对齐访存接口虽然解决了非对齐访存性能下降的问题,但两条非对齐存取指令相对单条浮点存取指令来说执行效率依旧较低.有时开发人员无法确定待访问地址是否对齐,便无法确定使用现有对齐访存接口还是非对齐访存接口.因此需要根据程序上下文,自动选择合适的指令接口.基于此,又设计了自适应多媒体指令访存接口:_mm_gsload_si64、_mm_gsstore_si64、_mm_gsload_si32和_mm_gsstore_si32.在提高多媒体指令优化程序的性能的同时,可以防止花费较长的时间来判断待访问地址所使用的访存指令.其中,_mm_gsstore_si64的接口实现如下:

extern __inline void FUNCTION_ATTRIBS

_mm_gsstore_si64(__m64 *dest,__m64 src)

{

if (!(((long)dest) & 7)) {

asm("sdc1 %1,%0 "

:"=m" (*dest)

:"f" (src)

:"memory"

);

} else {

asm("gssdlc1 %1,7(%0) "

"gssdrc1 %1,0(%0) "

:"r" (dest),"f" (src)

:"memory"

);

}

}

3.2 接口自适应择优算法

非对齐访存接口可以解决非对齐问题,自适应多媒体指令访存接口用以解决两条非对齐指令性能偏低的问题.因此,在具体实践过程中,若确定地址是4字节或8字节对齐的情况下使用现有访存接口:_mm_load_si32、_mm_store_si32、_mm_load_si64和_mm_store_si64;若不确定地址是否对齐的情况下,且同一地址只进行了一次访存操作则使用自适应多媒体指令防存接口:_mm_gsload_si32、_mm_gsstore_si32、_mm_gsload_si64和_mm_gsstore_si64;若不确定地址是否对齐且同一地址进行了多次访存操作则需对地址进行判断,若地址是4字节或8字节对齐,使用接口_mm_load_si32、_mm_store_si32、_mm_load_si64和_mm_store_si64,否则使用接口_mm_loadu_si32、_mm_storeu_si32、_mm_loadu_si64和_mm_storeu_si64.具体算法流程如图2所示,通过上述操作可使优化函数在地址非对齐时不会出现性能大幅下降的情况.

图2 接口自适应择优算法流程图Fig.2 Flow chart of interface adaptive optimization algorithm

4 LibYUV实验结果和分析

LibYUV是Google开源的实现各种YUV与RGB色彩空间之间相互转换、旋转、缩放的库,并且自带丰富的测试用例用于保证各个平台的优化在功能和性能上的可靠性.在保证龙芯多媒体指令优化功能测试正确的前提下,利用其性能测试来评测多媒体指令优化提升的效果[11].在这一过程中,发现在使用龙芯多媒体指令优化后,大多数测试用例普遍获得了不错的性能提升;但有些测试用例出现了性能没有提升,反而急剧下降的情况[12].经过GDB逐条指令分析,确定了这与程序访问非对齐地址有关,性能下降的测试用例后缀名带有_unaligned标记,但一些不带_unaligned标记的测试用例有时也会出现非对齐访存性能下降问题.从源代码中分析测试用例的设计,_unaligned标记的测试用例故意移动了指向待操作数据的指针,造成起始地址偏移到非对齐地址上,这是设计者为了LibYUV的可移植性和可靠性做出的特殊处理.

利用LibYUV的性能测试手段,表1随机列举了若干函数与其对应的测试用例在3种情形下的性能统计数据,数值越小代表性能越好.其中“原始函数”表列代表函数未优化前测试用例的执行时间,它是计算性能提升比例的基准值.

(1)

表1中“优化函数应用算法前/提升比例”表列是使用多媒体指令对函数进行优化后测试用例的执行时间,以及与基准值的比例,负号表示性能下降,计算方式如公式(1)所示.需要注意的是此处使用多媒体指令进行函数优化,优化时按通用做法使用现有访存接口.如果数据是对齐的,优化函数会有普遍的性能提升;如果测试用例需要访问非对齐地址上的数据,会造成优化函数性能的下降.

表1中“接口自适应择优算法/提升比例”表列表示在多媒体指令优化的基础上,应用接口自适应择优算法,把先前多媒体指令优化的访存接口按算法逻辑进行简单替换.即若能确定数据是对齐的,多媒体指令优化函数不需要改变,依旧使用现有访存接口;若不确定数据是否对齐且只执行一次访存操作,把访存接口替换为自适应多媒体指令访存接口;若确定数据是非对齐的,把访存接口替换为非对齐访存接口.

图3用折线图的形式描述了表1中性能统计数据的变化情况.圆点标记的曲线代表多媒体指令优化函数应用接口自适应择优算法前,正方形标记的曲线代表在多媒体指令优化的基础上应用自适应择优算法.

如图3所示,圆点标记的曲线普遍在零刻度线以下,9个测试用例中有6个出现了性能下降,即在地址非对齐时多媒体指令优化函数性能非但没有提升反而普遍低于原始函数的性能.余下的3个测试用例虽然性能得到提升,但提升比例较小,不符合多媒体指令优化的预期收益.优化后的SobelXRow_C函数性能下降最为明显,下降了1.07倍.可见在龙芯平台上进行多媒体指令优化,优化函数访问非对齐数据时会抵消并行计算带来的性能提升,造成程序性能的下降.

表1 LibYUV的性能统计数据表Table 1 Performance statistics of LibYUV

图3中正方形标记的曲线全部高于圆点标记的曲线,且所有的数据都为正值,9个测试用例平均有40%的性能提升,比较符合预期,表明了所提算法在数据非对齐的情况下依旧有较高的性能.I422ToYUY2Row_C函数性能提高比例最大,提升76%,9个函数最低的也有11%的性能提升.MergeUVRow_C的优化函数性能在应用自适应择优算法前后并未变化,说明此函数操作的数据是自然对齐的.

图3 优化函数应用接口自适应择优算法前后对比曲线图Fig.3 Before and after comparison curve of optimization function apply interface adaptive optimization algorithm

在LibYUV库优化过程中,除了使用多媒体指令技术进行优化外,还增加对非对齐访存问题的处理,并且针对某些特殊运算进行算法级优化,比如饱和处理、循环展开和尽可能消除乘法运算等,取得了不错的成果.开发人员在进行多媒体指令优化时,可以考虑使用接口自适应择优算法,既能提高优化函数的性能,又能保证优化函数在数据非对齐场景下的性能.

5 总 结

论文根据龙芯处理器的特点,为非对齐访存指令设计调用接口,并提出接口自适应择优算法,解决了龙芯多媒体指令优化时地址非对齐造成优化函数性能下降的问题.

论文的另一部分工作是对LibYUV库使用龙芯多媒体指令进行了全面优化,提高了LibYUV在龙芯平台上的表现能力,相关工作成果已推送至谷歌LibYUV开源社区.在下一步的工作中,要继续使用龙芯多媒体指令完成其它媒体库的优化工作,增强国产计算机平台上对不同多媒体格式的转换效率.随着龙芯生态体系的不断完善以及应用普及的不断扩大,国产CPU将会迎来更好的明天.

猜你喜欢
测试用例龙芯指令
基于国产化龙芯的动环数据采集系统
基于关键点的混合式漏洞挖掘测试用例同步方法
基于抽象汇编指令的恶意软件家族分类方法
《单一形状固定循环指令G90车外圆仿真》教案设计
新机研制中总装装配指令策划研究
面向多目标测试用例优先排序的蚁群算法信息素更新策略
“龙芯1号”:电脑中国“芯”
“龙芯1号”:电脑中国“芯”
太空第一人
测试用例集的优化技术分析与改进