ARM霓虹灯性能问题

时间:2013-06-10 15:44:57

标签: c arm neon

考虑以下两段代码,第一段是C版:

void __attribute__((no_inline)) proj(uint8_t * line, uint16_t length)
{
    uint16_t i;
    int16_t tmp;
    for(i=HPHD_MARGIN; i<length-HPHD_MARGIN; i++) {
        tmp = line[i-3] - 4*line[i-2] + 5*line[i-1] - 5*line[i+1] + 4*line[i+2] - line[i+3];
        hphd_temp[i]=ABS(tmp);
    }
}

第二个是使用氖内在函数的相同功能(边框除外)

void  __attribute__((no_inline)) proj_neon(uint8_t * line, uint16_t length)
{
    int i;
    uint8x8_t b0b7, b8b15, p1p8,p2p9,p4p11,p5p12,p6p13, m4, m5;
    uint16x8_t result;

    m4 = vdup_n_u8(4);
    m5 = vdup_n_u8(5);
    b0b7 = vld1_u8(line);
    for(i = 0; i < length - 16; i+=8) {
        b8b15 = vld1_u8(line + i + 8);
        p1p8  = vext_u8(b0b7,b8b15, 1);
        p2p9  = vext_u8(b0b7,b8b15, 2);
        p4p11 = vext_u8(b0b7,b8b15, 4);
        p5p12 = vext_u8(b0b7,b8b15, 5);
        p6p13 = vext_u8(b0b7,b8b15, 6);

        result = vsubl_u8(b0b7, p6p13); //p[-3]
        result = vmlal_u8(result, p2p9, m5); // +5 * p[-1];
        result = vmlal_u8(result, p5p12, m4);// +4 * p[1];
        result = vmlsl_u8(result, p1p8, m4); //-4 * p[-2];
        result = vmlsl_u8(result, p4p11, m5);// -5 * p[1];
        vst1q_s16(hphd_temp + i + 3, vabsq_s16(vreinterpretq_s16_u16(result)));
        b0b7 = b8b15;
    }
    /* todo : remaining pixel */

}

我对性能提升感到失望:它大约是10-15%。如果我查看生成的程序集:

  • C版本在108指令循环中转换
  • Neon版本在72指令循环中转换。

但是霓虹灯代码中的一个循环计算的数据是通过C循环迭代的8倍,因此应该看到一个显着的改进。

你对这两个版本之间的微小差异有什么解释吗?

其他细节: 测试数据是10 Mpix图像,C版本的计算时间约为2秒。

CPU:ARM cortex a8

1 个答案:

答案 0 :(得分:4)

我会猜测并说缓存(数据)是你没有看到预期的巨大性能提升的原因。虽然我不知道你的芯片组是否支持缓存或者在什么级别,如果数据跨越缓存行,对齐性差,或者在CPU同时执行其他操作的环境中运行(中断,线程等) 。),那也可能使你的结果变得混乱。