Как повернуть вектор SSE/AVX

Мне нужно выполнить операцию вращения с минимальным количеством тактов. В первом случае допустим __m128i как источник и тип dest:

source: || A0 || A1 || A2 || A3 ||
  dest: || A1 || A2 || A3 || A0 ||
dest = (__m128i)_mm_shuffle_epi32((__m128i)source, _MM_SHUFFLE(0,3,2,1));

Теперь я хочу сделать то же самое с встроенными функциями AVX. Итак, допустим на этот раз __m256i как источник и тип dest:

source: || A0 || A1 || A2 || A3 || A4 || A5 || A6 || A7 ||
  dest: || A1 || A2 || A3 || A4 || A5 || A6 || A7 || A0 ||

В свойствах AVX отсутствует основная часть соответствующих операций SSE. Возможно, есть какой-то способ получить желаемый выход, работающий с версией с плавающей точкой.

Я пробовал:

dest = (__m256i)_mm256_shuffle_ps((__m256)source, (__m256)source, _MM_SHUFFLE(0,3,2,1));

но я получаю:

|| A0 || A2 || A3 || A4 || A5 || A6 || A7 || A1 ||

Любая идея о том, как эффективно решить эту проблему? (без смешивания операций SSE и AVX и без "ручного" инвертирования A0 и A1

Спасибо заранее!

Ответы

Ответ 1

Мое решение:

__m256 tmp =  ( __m256 ) _mm256_permute_ps((__m256)_source, _MM_SHUFFLE ( 0,3,2,1 ));
* ( _dest ) =  ( __m256i) _mm256_blend_ps(tmp, _mm256_permute2f128_ps ( tmp,tmp,1 ), 136);  

Ответ 2

Я еще не проверял, что происходит с AVX, но, по крайней мере, для SSE, вы считали _mm_align*?

Например, это поворачивает байтовый вектор на 2 байта:

__m128i v;
v = _mm_alignr_epi8 (v, v, 2) // v = v[2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1]

Это может быть одна инструкция. Также такими операциями являются lat 1/tp 1, то есть быстро.

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