Как закодировать a[i]=b[c[i]] на внутренней функции ARM NEON SIMD

Я пытаюсь перевести этот код C/C++ во встроенную функцию SIMD.

for(int i=0 ; i < length ; i++)
    A[i] = B[C[i]];

Я могу перевести приведенный ниже код (C/C++)

for(int i=0 ; i < length ; i++)
    A[i] = B[i];

в код SIMD (используя встроенную функцию)

for(int i=0 ; i < length-16 ; i+=16) {
    uint8x16_t v0 = vld1q_u8(A+i);
    vst1q_u8(A+i, v0);
}

Я знаю, что ключевое слово чередуется, чтобы решить эту проблему. Но я не могу найти решение.

Спасибо.

Изменить
For more information

unsigned char A [32] = {0,}; // Output Array
unsigned char B [20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; // An array with values to pass to A Array
unsigned int C [32] = {19,15,11,10,5,3,6,4,5,19,10,14,16,14,8,9,10,20,11,1, 0, 3, 5, 19, 20, 11, 13, 9, 30, 31, 7}; // An array with the index information of the B array.

Есть ли внутренняя функция, которая может сделать следующий код?

int length = 32;
For (int i = 0; i < length-8; i+=8)
{
    Uint8x8_t v_idx = vld1_u8 (C + i);
    Uint8x8_t v = func (A, v_idx); // func (uint8_t, uint32x4_t)
    vst1_u8(C+i, v);
}

Выведет 20, 16, 12, 11, 6, 4, 7, 5, 6, 6, 20, 11, 15, 17, 15, 9, 10, 11, 21, 12, 2, 1, 4, 6, 20, 21, 12, 14, 10, 31, 32, 8

[Примечание]
A и B являются типами uint8_t *, поскольку они являются изображениями со значениями от 0 до 255, а C является типом uint32_t *, поскольку они индексируются индексом B.


person Byeongju Park    schedule 04.06.2017    source источник
comment
Это не чередование, если только C не имеет определенной структуры. В общем, это сбор, я надеюсь, что это не так. Что такое C?   -  person harold    schedule 04.06.2017
comment
@harold Я знал неверную информацию, спасибо. C — это массив со значением индекса B.   -  person Byeongju Park    schedule 05.06.2017
comment
Так что это общий сбор, насколько я знаю, у NEON такого нет.   -  person harold    schedule 05.06.2017
comment
Ты прав. В конце концов, я решил загрузить 16 значений, каждое из которых использовало vld1q_lane_u8 при загрузке.   -  person Byeongju Park    schedule 07.06.2017


Ответы (1)


Немного сложно быть уверенным, так как вы не предоставили много информации, но vqtbl1_u8 может быть тем, что вы ищете. Это только для AArch64, хотя vtbl1_u8 доступен на armv7.

Краткий пример:

int main (void) {
  uint8_t bp[] = { 1,  1,  2,  3,  5,  8, 13, 21 };
  uint8_t cp[] = { 0,  2,  4,  6,  1,  3,  5,  7 };

  uint8x8_t b = vld1_u8(bp);
  uint8x8_t c = vld1_u8(cp);

  uint8x8_t a = vtbl1_u8(b, c);
  uint8_t ap[8];
  vst1_u8(ap, a);

  for (int x = 0 ; x < 8 ; x++)
    printf("%3u ", ap[x]);
  printf("\n");

  return 0;
}

Выведет 1 2 5 13 1 3 8 21

person nemequ    schedule 04.06.2017
comment
Это очень помогло. Спасибо. Однако длина массивов B и`C` больше 10 миллионов. Как вы можете догадаться, C Array — это массив с индексной информацией массива B. Я добавил вопрос для получения дополнительной информации. - person Byeongju Park; 05.06.2017