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

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

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 как исходный и целевой тип:

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

Заранее спасибо!


person user1584773    schedule 10.08.2012    source источник
comment
У вас нет большого опыта работы с SSE и AVX, но во второй строке кода, если тип dest __m256, почему вы выполняете приведение к __m128i?   -  person dario_ramos    schedule 10.08.2012
comment
Конечно это был __m256i, спасибо!   -  person user1584773    schedule 10.08.2012
comment
Нет, я просто ошибся с функцией вырезания и вставки ..   -  person user1584773    schedule 11.08.2012
comment
Похоже, все полезные инструкции есть в AVX2 (почему они не выпустили эту сначала?)   -  person harold    schedule 11.08.2012


Ответы (2)


Мое решение:

__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);  
person user1584773    schedule 02.12.2012
comment
Есть ли шанс на объяснение 2 сразу после того, как вы перейдете на вторую строку? (1 и 136) Я читал документацию, но до сих пор не понимаю, почему именно эти значения вам нужны для этого. - person Orvid King; 14.05.2014
comment
@OrvidKing: permute2f128(tmp,tmp,1) меняет местами верхнюю и нижнюю полосы 128b. 136 = 0x88 = взять верхний элемент из одного вектора, другие элементы из другого (так, 0x8 в каждой полосе, потому что blendps использует две половины imm8 для двух полос.) - person Peter Cordes; 10.09.2015

Я еще не проверял, как обстоят дела с 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, вероятно, доставит вам немало хлопот с этим подходом, поэтому адаптация может оказаться бесполезной.

person mafu    schedule 05.05.2017