2016-09-19 3 views
0

Я довольно новичок в программировании ARM и NEON, мне поручена задача оптимизации функции SAD (Sum of Absolute Difference). Я не знаю, с чего начать, я попробовал несколько способов создания кода 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; 
} 

Этот код имеет:

  • только один цикл
  • Там нет операторов перерыв в цикле
  • Указатели охраняются __restrict
+0

Вы также можете рассмотреть использование векторного типа данных, такого как uint8x8x4_t, который определяется как простой массив типа uint8x8_t: typedef struct int8x8x4_t { int8x8_t val [4]; } int8x8x4_t; – nachiketkulk

+0

Также вы можете использовать функцию uint8_t vaddvq_u8(), чтобы добавить все элементы в полосе в одну команду, если вы используете код в 64-битной архитектуре. – nachiketkulk

Смежные вопросы