Сравнение и извлечение с использованием SSE

Каков наилучший способ попарного сравнения двух целочисленных регистров и извлечения одинаковых элементов с помощью инструкций SSE? Например, если a = [6 4 7 2] и b = [2 4 9 2] (каждый регистр содержит четыре 32-битных целых числа), то результатом должно быть [4 2 x x]. Альтернативная форма этого вопроса - как получить двоичную маску из одинаковых элементов (..0101b), которая может быть использована для перестановки или как индекс для поиска параметра инструкции перестановки в предварительно вычисленной таблице.

Невозможно извлечь и переместить равные элементы одной инструкцией. Но маска равных элементов может быть легко получена с помощью pcmpeqd:

__m128i zero = _mm_set1_epi32(0);
__m128i a = _mm_set_epi32(6, 4, 7, 2);
__m128i b = _mm_set_epi32(2, 4, 9, 2);

__m128i mask = _mm_cmp_epi32(a, b);     // mask is now 0, -1, 0, -1
mask = _mm_sub_epi32(zero, mask);       // mask is now 0,  1, 0,  1

Редактирование: Если вам нужен некоторый индекс для таблицы поиска с перетасованными константами, вам нужны дополнительные операции. Например,

static const __m128i zero = _mm_set1_epi32(0);
static const __m128i bits = _mm_set_epi32(1,2,4,8);

__m128i a = _mm_set_epi32(6, 4, 7, 2);
__m128i b = _mm_set_epi32(2, 4, 9, 2);

__m128i bitvector = _mm_and_si128(bits, _mm_cmp_epi32(a, b));
bitvector = _mm_hadd_epi32(bitvector, bitvector);
bitvector = _mm_hadd_epi32(bitvector, bitvector);
// now a index from 0...15 is the the low 32 bit of bitvector

Возможно, существуют лучшие алгоритмы, чем использование таблицы поиска для вычисления шаффла, возможно, вычисление шаффла напрямую с помощью мультипликации De Bruijn. Кроме того, если у вас есть более 4 интов для сравнения, дополнительные 4 инта будут стоить только одного дополнительного фадд.

Комментарии (1)
Решение

Я бы, вероятно, использовал вариант того, что предлагает drhirsch:

int index = _mm_movemask_ps((__m128)_mm_cmp_epi32(a, b));

Это даст вам тот же индекс, который можно использовать для поиска маски шаффла, используя только две операции.

Комментарии (0)