Бесполезно генерировать немедленный во время выполнения, если вы не JIT новый код.Непосредственный - это байт, который буквально является частью кодирования инструкции машинного кода.Прекрасно, если у вас есть тасование с постоянной во время компиляции (после вставки + расширение шаблона), иначе забудьте о тех тасованиях, которые принимают операнд управления как целое число 1 .
До AVX тасование с переменным управлением only было SSSE3 pshufb
.(_mm_shuffle_epi8
).Это по-прежнему единственная 128-битная (или внутренняя) целочисленная команда перемешивания в AVX2, и я думаю, что AVX512.
AVX1 добавил некоторые 32-битные в строкепеременные тасовки, например vpermilps
(_mm_permutevar_ps
).AVX2 добавил целое число пересечения полосы и тасование FP, но как ни странно, нет 128-битной версии vpermd
.Возможно, потому что у микроархитектур Intel нет штрафов за использование преобразований FP в целочисленных данных.(Что верно для семьи Сэндибридж, я просто не знаю, было ли это частью обоснования дизайна ISA).Но вы могли бы подумать, что они добавили бы __m128i
встроенных функций для vpermilps
, если бы это было то, что вы «должны» делать.Или, может быть, разработчики компиляторов / встроенных программ не согласились с людьми из набора инструкций asm?
Если у вас есть переменный вектор времени выполнения из 32-битных индексов и вы хотите сделатьв случайном порядке с 32-битной гранулярностью, безусловно, лучше всего использовать AVX _mm_permutevar_ps
.
_mm_castps_si128( _mm_permutevar_ps (_mm_castsi128_ps(a), idx) )
По крайней мере, в Intel это даже не представитлюбая дополнительная задержка обхода при использовании между целочисленными инструкциями, такими как paddd
;т. е. FP shuffles специально (не смешивает) не взимают штраф за использование целочисленных данных в процессорах семейства Sandybridge .
Если есть какие-либо штрафы для AMD Bulldozer или Ryzen,это незначительно и определенно дешевле, чем стоимость вычисления вектора управления тасованием для (v)pshufb
.
Использование vpermd ymm
и игнорирование старших 128 битов ввода и вывода (т. е. с использованием встроенных преобразований) будет намного медленнее на AMD (потому что его 128-битная SIMD-конструкция должна разделять 256-битные тасовки с пересечением полос на несколько мопов), а также хуже на Intel, где она делает задержку 3c вместо 1 цикла.
@ Ответ Ивилла показывает способ расчета вектора управления байтовыми индексами для перемешивания для pshufb
из вектора 4x32-битных индексов двойного слова.Но он использует SSE4.1 pmulld
, который составляет 2 мопа на большинстве процессоров, и может легко стать более узким местом, чем тасование.(См. Обсуждение в комментариях под этим ответом.) Особенно на более старых процессорах без AVX, некоторые из которых могут делать 2 pshufb
за такт в отличие от современного Intel (в Haswell и более поздних версиях имеется только 1 порт случайного воспроизведения и легко узкое место в случайном порядке. IceLake добавит еще одинпорт shuffle, в соответствии с презентацией Intel Sunny Cove.)
Если вам нужно написать версию SSSE3 или SSE4.1, вероятно, все же лучше использовать только SSSE3 и использовать pshufb
плюс сдвиг влеводублировать байт внутри dword перед ORing в 0,1,2,3
в младшие биты, а не pmulld
.SSE4.1 pmulld
имеет несколько мопов и даже хуже, чем pshufb
на некоторых процессорах с медленным pshufb
.(Вы можете вообще не выиграть от векторизации на процессорах только с SSSE3, а не с SSE4.1, то есть с Core2 первого поколения, потому что он имеет медленный выпуск pshufb
.)
На Core2 второго поколения, иGoldmont, pshufb
- инструкция с одним циклом с задержкой в 1 цикл.На Silvermont и Core 2 первого поколения это не так хорошо.Но в целом я бы порекомендовал pshufb
+ pslld
+ por
, чтобы вычислить управляющий вектор для другого pshufb
, если AVX недоступен .
Дополнительный случайный порядокподготовиться к перемешиванию гораздо хуже, чем просто использовать vpermilps
на любом процессоре, поддерживающем AVX.
Сноска 1 :
Вам придетсяиспользуйте switch
или что-то еще, чтобы выбрать путь к коду с правильным целым числом времени компиляции, и это ужасно;Только учтите, что если у вас нет даже SSSE3.Это может быть хуже, чем скаляр, если ветвь таблицы переходов не предсказывает идеально.