2016-09-19 198 views
0

对于ARM和NEON编程来说,我相当新,我已经给了一个优化SAD(绝对差值和)函数的任务。我不知道从哪里开始,我尝试了几种不成功的方法来生成NEON代码。 顺序功能看起来是这样的:ARM NEON 8x8 SAD操作

void sad_block_8x8(uint8_t *block1, uint8_t *block2, int stride, int *result) 
{ 
    int u, v; 

    *result = 0; 

    for (v = 0; v < 8; ++v) 
    { 
     for (u = 0; u < 8; ++u) 
     { 
      *result += abs(block2[v*stride+u] - block1[v*stride+u]); 
     } 
    } 
} 

所以我的问题是:

  1. 如何加载寄存器每次迭代
  2. 我怎么做计算,并将其存储到变量结果

任何帮助将非常感谢!

好......所以我的第一次尝试是这样的(它的工作原理,但我知道是一个非常霓虹灯代码)

void sad_block_8x8_2(uint8_t *block1, uint8_t *block2, int stride, int *result) 
{ 
int u, v; 
uint8x8_t m_1, m_2, m_o; 
uint8_t* test; 
test = (uint8_t*)malloc(v*u*sizeof(uint8_t));; 
*result = 0; 
for (v = 0; v < 8; ++v) 
{ 
    for(u = 0; u < 8; ++u) 
    { 
     m_1 = vld1_u8(&block1[v*stride]); 
     m_2 = vld1_u8(&block2[v*stride]); 

     m_o = vabd_u8(m_2, m_1); 
     vst1_u8(&test[v], m_o); 
     //printf("%d ", test[v]); 
     *result += (int)test[v]; 
    } 
} 
} 

任何帮助吗?

+1

输入数据块应该是'const'。您是否尝试过支持NEON的编译器,它可能会自动为您编译? – unwind

+0

要获得8x8到8x1双向您可以用'uint16x8_t vabal_u8(uint16x8_t,uint8x8_t,uint8x8_t)'在arm_neon.h – user3528438

回答

0

这是好一点,更清晰的执行SAD算法你想要的:

void neon_sad_block_8x8(uint8_t *__restrict block1, uint8_t * __restrict block2, int stride, int *__restrict result) 
{ 
     int i, j; 
     uint8x8_t neon_block1; 
     uint8x8_t neon_block2; 
     uint8x8_t res; 
     int sum = 0; 
     for (i = 0; i < 8; i++) {             
      neon_block1 = vld1_u8(&block1[i * stride]);      
      neon_block2 = vld1_u8(&block2[i * stride]);      
      res = vabd_u8(neon_block2, neon_block1);       
      sum += res[0] + res[1] + res[2] + res[3] + res[4] + res[5] + res[6] + res[7]; 
     } 
     *result = sum; 
} 

此代码有:

  • 只有一个循环
  • 有在循环
  • 没有break语句
  • 指针被__restrict守卫
+0

你也可以考虑使用像它被定义为类型uint8x8_t类型的简单数组uint8x8x4_t矢量数据类型: typedef结构int8x8x4_t { int8x8_t val [4]; } int8x8x4_t; – nachiketkulk

+0

如果您在64位体系结构上运行代码,您也可以使用uint8_t vaddvq_u8()函数在一条指令中添加通道中的所有元素。 – nachiketkulk