2016-09-19 211 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