Как сравнить два вектора с помощью SIMD и получить один логический результат?

У меня есть два вектора по 4 целых числа в каждом, и я хотел бы использовать команду SIMD для их сравнения (скажем, сгенерировать вектор результатов, где каждая запись равна 0 или 1 в зависимости от результата сравнения).

Затем я хотел бы сравнить результирующий вектор с вектором из 4 нулей и, только если они равны, что-то сделать.

Вы знаете, какие команды SIMD я могу использовать для этого?


person N.M    schedule 29.07.2011    source источник
comment
Какую архитектуру вы используете? Все SIMD разные.   -  person Phonon    schedule 29.07.2011
comment
Я очень новичок в этом, поэтому, пожалуйста, простите мое незнание. Я пытаюсь включить команды SIMD, используя платформу Intel Parallel studio (это каким-либо образом отвечает на ваш вопрос?).   -  person N.M    schedule 29.07.2011


Ответы (1)


Чтобы сравнить два вектора SIMD:

#include <stdint.h>
#include <xmmintrin.h>

int32_t __attribute__ ((aligned(16))) vector1[4] = { 1, 2, 3, 4 };
int32_t __attribute__ ((aligned(16))) vector2[4] = { 1, 2, 2, 2 };
int32_t __attribute__ ((aligned(16))) result[4];

__m128i v1 = _mm_load_si128((__m128i *)vector1);
__m128i v2 = _mm_load_si128((__m128i *)vector2);
__m128i vcmp = _mm_cmpeq_epi32(v1, v2);
_mm_store_si128((__m128i *)result, vcmp);

Примечания:

  • данные считаются 32-битными целыми числами
  • vector1, vector2, result все должны быть выровнены по 16 байт
  • результат будет -1 для равно, 0 для не равно ({ -1, -1, 0, 0 } для приведенного выше примера кода)

ОБНОВЛЕНИЕ

Если вам нужен только один логический результат для случая, когда все 4 элемента совпадают, вы можете сделать это следующим образом:

#include <stdint.h>
#include <xmmintrin.h>

int32_t __attribute__ ((aligned(16))) vector1[4] = { 1, 2, 3, 4 };
int32_t __attribute__ ((aligned(16))) vector2[4] = { 1, 2, 2, 2 };

__m128i v1 = _mm_load_si128((__m128i *)vector1);
__m128i v2 = _mm_load_si128((__m128i *)vector2);
__m128i vcmp = _mm_cmpeq_epi32(v1, v2);
uint16_t mask = _mm_movemask_epi8(vcmp);
int result = (mask == 0xffff);
person Paul R    schedule 29.07.2011
comment
Спасибо. Когда я получаю вектор результатов, есть ли простой способ проверить, все ли это нули (я хотел бы иметь логическое значение, представляющее, все ли это нули или нет). - person N.M; 29.07.2011
comment
Я мог бы использовать _mm_cmpgt_epi32, если хочу получить результат лучше, верно? - person N.M; 29.07.2011
comment
@ N.M: да, _mm_cmpgt_epi32. - person Paul R; 29.07.2011
comment
Вам нужно [] после vector1 и 2 нет? - person Simon; 09.11.2015
comment
@Simon: хороший улов - прошло 4 года, чтобы все заметили! - person Paul R; 09.11.2015
comment
Опечатка: _mm_movemask_epi8 возвращает int и не __m128i. - person Heygard Flisch; 21.11.2016
comment
@HeygardFlisch: спасибо - обычно я тестирую публикуемый мной код - в этот раз я явно этого не делал! - person Paul R; 21.11.2016
comment
маска должна быть uint16_t, иначе 0xffff вне допустимого диапазона. - person user1794469; 08.02.2018