在ADSP-BF561上使用x264(7):x264_pixel_satd_8x4

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文适用于

ADSP-BF561

Visual DSP++ 5.0 (update 7)

x264-snapshot-20091118-2245

 

 

 

 

 

欢迎转载,但请保留作者信息

 

1.1    代码距离导致的效率差异

发现了一个疏忽,排名第二的x264_pixel_satd_8x4函数没有放到L1_code中,改正错误,再运行:

       encoded 301 frames, 2.02 fps, 1081.88 kb/s

86802Mcycle,怎么可能?速度反而变慢了!下降了386Mcycle

退回上一步再验证,还是如此,晕……………………..@#@

究竟是什么导致这样的结果??

想来这个结果只能和调用者有关。

x264_pixel_satd_8x4和它的调用者位于同一块内存区域时(<64K),编译器只要生成4个字节的call指令:

call x264_pixel_satd_8x4

当把这个函数放到L1时时,编译器只能生成这样的指令:

P1.L = 0x330a;

P1.H = 0xffa0;

CALL (P1);

差距就在这里。

本来程序在L1里面和SDRAM里面执行应该是有很大区别的,但在启用cache的情况下,如果这段代码恰好就位于cache中,就变得没有什么区别了。

我们尝试将其中的一个调用函数x264_pixel_satd_16x16放到L1中,再执行:

encoded 301 frames, 2.02 fps, 1081.88 kb/s

总共86614Mcycle

我们再尝试将其它调用者放到L1中,将下面的函数放到L3

add4x4_idct

运行结果:

       encoded 301 frames, 2.02 fps, 1081.88 kb/s

总共耗费了86599Mcycle

运行结果证实了我们的猜测。

看来我们现在只能把x264_pixel_satd_8x4放到L3中,仍然把add4x4_idct放到L1,因为这样效率最高,哈哈。

1.2    专用指令导致的效率差异

下面我们再看看x264_pixel_satd_8x4这个函数本身有没有可以优化的地方:

#define HADAMARD4(d0,d1,d2,d3,s0,s1,s2,s3) {/

    int t0 = s0 + s1;/

    int t1 = s0 - s1;/

    int t2 = s2 + s3;/

    int t3 = s2 - s3;/

    d0 = t0 + t2;/

    d2 = t0 - t2;/

    d1 = t1 + t3;/

    d3 = t1 - t3;/

}

 

// in: a pseudo-simd number of the form x+(y<<16)

// return: abs(x)+(abs(y)<<16)

static ALWAYS_INLINE uint32_t abs2( uint32_t a )

{

    uint32_t s = ((a>>15)&0x10001)*0xffff;

    return (a+s)^s;

}

 

static NOINLINE int x264_pixel_satd_8x4( uint8_t *pix1, int i_pix1, uint8_t *pix2, int i_pix2 )

{

    uint32_t tmp[4][4];

    uint32_t a0,a1,a2,a3;

    int sum=0, i;

    for( i=0; i<4; i++, pix1+=i_pix1, pix2+=i_pix2 )

    {

        a0 = (pix1[0] - pix2[0]) + ((pix1[4] - pix2[4]) << 16);

        a1 = (pix1[1] - pix2[1]) + ((pix1[5] - pix2[5]) << 16);

        a2 = (pix1[2] - pix2[2]) + ((pix1[6] - pix2[6]) << 16);

        a3 = (pix1[3] - pix2[3]) + ((pix1[7] - pix2[7]) << 16);

        HADAMARD4( tmp[i][0], tmp[i][1], tmp[i][2], tmp[i][3], a0,a1,a2,a3 );

    }

    for( i=0; i<4; i++ )

    {

        HADAMARD4( a0,a1,a2,a3, tmp[0][i], tmp[1][i], tmp[2][i], tmp[3][i] );

        sum += abs2(a0) + abs2(a1) + abs2(a2) + abs2(a3);

    }

    return (((uint16_t)sum) + ((uint32_t)sum>>16)) >> 1;

}

在这里,我们发现了一个叫abs2的内联函数,它用以将一个无符号整数分成高16位和低16位,分别取其绝对值。我们将它用561的向量指令重写:

// in: a pseudo-simd number of the form x+(y<<16)

// return: abs(x)+(abs(y)<<16)

static ALWAYS_INLINE uint32_t abs2( uint32_t a )

{

    uint32_t s;

    asm(

    "%0 = abs %0 (v);"

    :"=d"(s)

    :"d"(a)

    );

    return s;

}

在改写之前,第二个for循环生成这样的指令:

 

在ADSP-BF561上使用x264(7):x264_pixel_satd_8x4_第1张图片

改写之后,生成的汇编就变成了:

 

在ADSP-BF561上使用x264(7):x264_pixel_satd_8x4_第2张图片

这里有个问题,采用向量计算与原算法相比,其计算结果略有差异:

比如0xffffffff,这个数它的高低16位都是-1,使用向量取绝对值可以得到0x00010001这样的结果,但如果是原算法则只能得到0x0000 0001这样的结果,累加下来之后的差距最大将达到4。不过这还在我们能忍受的范围之内,呵呵。

改写之后导致此函数的cycle数从340下降到248,再运行我们的程序:

encoded 301 frames, 2.20 fps, 1222.74 kb/s

总共消耗了79702Mcycle,效率提高了7%

 

1.3    存储位置导致的效率差异

在这个函数中,使用了一个tmp[4][4]的数组,我们直接将之放入L1,再运行:

encoded 301 frames, 2.52 fps, 1131.15 kb/s

总共69572M cycle,效率提高了12%

我们希望最终能够用汇编实现整个函数,但是依照先易后难的原则,目前暂且放下。

 

 

 

 

近日,我家6岁的小姑娘参加了第六届POP全国少儿英语风采大赛,拉票进行中(2011-6-15前)。

请帮忙点击新东方网站的链接:

http://popdasai.xdf.cn/toupiao.php?do=space&uid=4237

投她一票,谢谢!

 

1       参考资料

ADSP-BF561上使用x2646):get_ref(2009-11-25)

ADSP-BF561上使用x2645):Writeback vs writethrough2009-11-24

ADSP-BF561上使用x2644):确认热点2009-11-24

ADSP-BF561上使用x2644):打开cache2009-11-24

ADSP-BF561上使用x2643):正确性验证2009-11-24

ADSP-BF561软件优化(2):移植x264(2009-11-19)

ADSP-BF561软件优化(1):开篇(2009-11-18)

 

 

你可能感兴趣的:(算法,优化,cache,汇编,存储,编译器)