В SSE3, инструкция PALIGNR выполняет следующие операции:_mm_alignr_epi8 (PALIGNR) эквивалент в AVX2
PALIGNR concatenates the destination operand (the first operand) and the source operand (the second operand) into an intermediate composite, shifts the composite at byte granularity to the right by a constant immediate, and extracts the right-aligned result into the destination.
Я в настоящее время в разгаре портирования моего SSE4 кода, чтобы использовать инструкции AVX2 и работают на 256bit регистров вместо 128bit. Наивно, я считал, что функция intrinsics _mm256_alignr_epi8
(VPALIGNR) выполняет ту же операцию, что и _mm_alignr_epi8
, только на 256-битных регистрах. К сожалению, это не совсем так. Фактически, _mm256_alignr_epi8
рассматривает 256-битный регистр как 2 128-битные регистры и выполняет 2 операции «выравнивания» в двух соседних 128-битных регистрах. Эффективно выполняет ту же операцию, что и _mm_alignr_epi8
, но на 2 регистрах одновременно. Это наиболее наглядно показано здесь: _mm256_alignr_epi8
В настоящее время мое решение продолжать использовать _mm_alignr_epi8
путем разделения YMM (256bit) регистрирует в двух XMM (128bit) регистры (высокий и низкий), например так:
__m128i xmm_ymm1_hi = _mm256_extractf128_si256(ymm1, 0);
__m128i xmm_ymm1_lo = _mm256_extractf128_si256(ymm1, 1);
__m128i xmm_ymm2_hi = _mm256_extractf128_si256(ymm2, 0);
__m128i xmm_ymm_aligned_lo = _mm_alignr_epi8(xmm_ymm1_lo, xmm_ymm1_hi, 1);
__m128i xmm_ymm_aligned_hi = _mm_alignr_epi8(xmm_ymm2_hi, xmm_ymm1_lo, 1);
__m256i xmm_ymm_aligned = _mm256_set_m128i(xmm_ymm_aligned_lo, xmm_ymm_aligned_hi);
Это работает, но должен быть лучший способ, не так ли? Возможно, существует более «общая» инструкция AVX2, которая должна использоваться для получения того же результата?
yup, это то же решение. но если это единственный способ, то это выглядит как большой надзор со стороны разработчиков инструкций AVX2. – eladidan
Я не мог заставить это скомпилировать ... Я получаю ошибку компиляции: «катастрофическая ошибка: Внутренний параметр должен быть немедленным значением» на следующей строке: «__m128i vouth = _mm_alignr_epi8 (v0l, v0h, n);». Существенно, потому что n не является абсолютным. Как вы могли обойти это? Я использую компилятор Intel C++ – eladidan
Он работает для меня, если n - постоянная времени компиляции - я тоже использую компилятор Intel ICC, но компилирую как C, а не C++, если это имеет значение, и это также работает для меня с gcc. –