Векторные инструкции ARM - 16 байтов против 8 байтов - PullRequest
1 голос
/ 23 января 2020

Я знаком с инструкциями SSE, но пытаюсь разобраться с основами сборки ARM (кодируется через C intrinsics). Меня смущает, как использовать инструкции vabal_u8 и vabal_high_u8, и, в частности, тот факт, что они принимают параметры другого типа (один принимает uint8x8, а другой - uint8x16).

Я считаю, что если у меня есть две переменные введите uint8x16, тогда я могу вычислить абсолютную разницу «высокой» половины этих векторов, используя vabal_high_u8, но как рассчитать абсолютную разницу «низкой» половины? Я не могу просто вызвать vabal_u8, потому что он ожидает тип ввода uint8x8, а не 8x16.

Мне кажется, что мне нужно искать метод извлечения младшей половины uint8x16 и представления его в виде uint8x8 (и я подозреваю, что на самом деле это просто приведение, которое не требует каких-либо базовых инструкций). Однако, если это так, я не могу понять, как это сделать. Кто-нибудь может помочь установить меня правильно?

Примечание 1. В целом я пытаюсь выполнить вычисление суммы абсолютных разностей для длинной строки байтов, и, похоже, vabal лучший способ добиться этого без переполнения типа uint8.

Примечание 2: Возможно, мне было бы лучше просто загрузить uint8x8 и использовать vabal_u8, а не пытаться работать с входами uint8x8, но это кажется, что должен быть способ сделать 8x16, как я пытаюсь ...?

Примечание 3: это будет намного проще в SSE, благодаря встроенной функции _mm_sad_epu8 c!

Обновление:

Я пытался описать то, что я «действительно» хотел сделать, но если я сведу это к моему основному вопросу о наборе векторных инструкций:

Описания для vabal_high_u8(uint16x8_t a, uint8x16_t b, uint8x16_t c) и vabal_u8 (uint16x8_t a, uint8x8_t b, uint8x8_t c) идентичны и читаются (выделено жирным шрифтом):

Абсолютная разница без знака и Накопленная длина , Эта инструкция вычитает векторные элементы в нижней или верхней половине второго исходного SIMD & FP-регистра из соответствующих векторных элементов первого исходного SIMD & FP-регистра и…

Это подразумевает Это пара инструкций, одна из которых может использоваться для работы с нижней половиной 16-битного вектора, а другая - для работы с верхней половиной 16-битного вектора, и, конечно, если вы можете сделать верхнее, то, безусловно, имеет смысл и способ сделать нижнее. Однако две доступные встроенные функции имеют разные типы входных параметров. Предположим, у меня уже есть uint8x16_t b и c. Я могу оперировать в верхней половине, используя vabal_high_u8. Как выполнить эквивалентную операцию на нижней половине? Я не могу использовать инструкцию партнера vabal_u8, потому что она принимает тип uint8x8_t вместо uint8x16_t. Нет vabal_ low _u8 (uint16x8_t a, uint8x16_t b, uint8x16_t c) ...

...