Преобразование кода в сборку Neon

Я работаю над переводом кода ниже в Neon Assembly. Любая помощь будет принята с благодарностью.

void sum(int length, int *a, int *b, int *c, int *d, char *result)
{
   int i;

   for (i = 0; i < length; i++)
      {
          int sum = (a[i] + b[i] + c[i] + d[i])/4;
          if (sum > threshold)
             result[i] = 1;
          else
             result[i] = 0;
      }
}

Фактический код представляет собой алгоритм бинаризации изображения. Приведенный выше код предназначен только для демонстрации идеи, а не для усложнения простых вещей.


person nasi    schedule 05.07.2012    source источник
comment
Нельзя ли просто запустить его через компилятор?   -  person Mysticial    schedule 05.07.2012
comment
просто включите переключатель на компиляторе, чтобы сгенерировать сборку, а затем переведите этот вывод в сборку Neon.   -  person AndersK    schedule 05.07.2012


Ответы (1)


Вот довольно простая реализация. Обратите внимание, что мы конвертируем проверку деления и порога только в проверку против threshold * 4 (чтобы устранить деление):

void sum(const int n, const int32_t *a, const int32_t *b, const int32_t *c, const int32_t *d, int32_t *result)
{
   const int32_t threshold4 = threshold * 4;
   const int32x4_t vthreshold4 = { threshold4, threshold4, threshold4, threshold4 };
   const uint32x4_t vk1 = { 1, 1, 1, 1 };
   int i;

   for (i = 0; i < n; i += 4)
   {
      int32x4_t va = vld1q_s32(&a[i]);    // load values from a, b, c, d
      int32x4_t vb = vld1q_s32(&b[i]);
      int32x4_t vc = vld1q_s32(&c[i]);
      int32x4_t vd = vld1q_s32(&d[i]);

      int32x4_t vsum = vaddq_s32(va, vb); // sum values form a, b, c, d
      vsum = vaddq_s32(vsum, vc);
      vsum = vaddq_s32(vsum, vd);

      uint32x4_t vcmp = vcgtq_s32(vsum, vthreshold4);
                                          // compare with threshold * 4
      int32x4_t vresult = (int32x4_t)vandq_u32(vcmp, vk1);
                                          // convert result to 0/1
      vst1q_s32(&result[i], vresult);     // store result
   }
}

Примечания:

  • полностью непроверенный код - может потребоваться дополнительная работа
  • result было изменено на int32_t * - его несложно упаковать в uint8_t, но это сильно усложняет первоначальный пример, поэтому я решил, что пока не буду его упрощать.
  • a, b, c, d, result все должны быть выровнены по 16 байтам
  • n должно быть кратно 4
  • сумма a, b, c, d должна соответствовать 32-битному целому числу со знаком
  • threshold * 4 должен соответствовать 32-битному целому числу со знаком
person Paul R    schedule 05.07.2012
comment
Спасибо, Пол. Поскольку источником является изображение в градациях серого, мне нужно загрузить uchar в значение int32x4_t. Я думаю использовать int32x4_t input = vshrn_n_u32(source, 24) // источник uint8_t. Подскажите, пожалуйста, как вы упаковываете? - person nasi; 21.08.2012
comment
Чтобы упаковать до 8 бит, вам нужно взять 4 x 4 x 32-битных вектора и использовать инструкции vmovn_xxx или vpadd_xxx для упаковки сначала в 2 x 8 x 16-битных векторов, а затем снова до одного 16 x 8-битного вектора. - person Paul R; 21.08.2012
comment
Спасибо @paul-r. На самом деле мы упаковываем из регистра q (128 бит) в регистр d (64 бит), поэтому я думаю, что это должен быть вектор 2x32x4 -> 2x16x4 -> 8x8. Я все еще работаю над реализацией этого (я совершенно новичок в Neon, поэтому это заняло у меня так много времени) - person nasi; 22.08.2012
comment
@PaulR - Можно ли что-нибудь сделать, чтобы ускорить эти инициализации: int32x4_t vthreshold4 = { threshold4, threshold4, threshold4, threshold4 } и uint32x4_t vk1 = { 1, 1, 1, 1 }. У меня есть функция на критическом пути кода, которая должна выполнять это несколько раз из-за спецификации алгоритма (криптографический хэш BLAKE2). - person jww; 07.05.2016
comment
@jww: компилятор должен быть достаточно умен, чтобы поднимать такие константы из любого охватывающего цикла, даже если это из встроенной функции - вы проверяли сгенерированный код? В противном случае вы можете просто передать инициализированные константы в функцию в качестве параметров. - person Paul R; 07.05.2016