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

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


person user1128016    schedule 12.05.2012    source источник
comment
Вычитание превратит равные пары чисел в 0.   -  person Alexey Frunze    schedule 12.05.2012


Ответы (2)


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

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

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

person Stephen Canon    schedule 13.05.2012

Невозможно извлечь и переместить одинаковые элементы с помощью одной инструкции. Но маску из равных элементов можно легко получить с помощью 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

Могут быть лучшие алгоритмы, чем использование таблицы поиска для вычисления тасования, возможно, вычисление тасования напрямую с использованием множителя Де Брёйна. OTOH, если у вас есть более 4 int для сравнения, дополнительные 4 int будут стоить только одного дополнительных phaddd.

person Gunther Piez    schedule 12.05.2012
comment
На самом деле я имел в виду битовую маску, которую можно использовать в инструкции тасования напрямую или как небольшой индекс для поиска маски в предварительно вычисленной таблице, то есть в этом примере mask = ..0101b = 5d. - person user1128016; 13.05.2012