Я уже некоторое время использую следующий "трюк" в коде C с SSE2 для чисел с плавающей запятой одинарной точности:
static inline __m128 SSEI_m128shift(__m128 data)
{
return (__m128)_mm_srli_si128(_mm_castps_si128(data), 4);
}
Для таких данных, как [1.0, 2.0, 3.0, 4.0]
, это приводит к [2.0, 3.0, 4.0, 0.0]
, т. Е. Выполняет сдвиг влево на одну позицию и заполняет структуру данных нулем. Если я правильно помню, указанная выше встроенная функция компилируется до одной инструкции (по крайней мере, с помощью gcc).
Я как-то не могу понять, что делать то же самое с AVX2. Как я мог добиться этого эффективным образом?
gcc
, я рекомендую использовать векторные расширения gcc вместо встроенных функций, специфичных для архитектуры, где это возможно. В частности, вы можете использовать__builtin_shuffle(data, (fvectype){0}, (ivectype){1, 2, 3, 4})
. Однако имейте в виду, что AVX-векторы длиной более 128 бит состоят из полос, а инструкции по пересечению полос (которые неизбежны при прямом расширении вашего примера) намного медленнее, чем в полосе движения. операций (~ в 3 раза медленнее), поэтому может быть хорошей идеей проверить, действительно ли вам это нужно. - person EOF   schedule 23.05.2020gcc
компилирует встроенные функции вектора gcc в следующую сборку:vmovaps %ymm0, %ymm1 vxorps %xmm0, %xmm0, %xmm0 vperm2f128 $33, %ymm0, %ymm1, %ymm0 vpalignr $4, %ymm1, %ymm0, %ymm0
. Вы можете перепроектировать это в Intel-Intrinsics, если хотите. В качестве альтернативы разумным решением будет внутренняя функция вектора gcc. - person EOF   schedule 23.05.2020vpermd
для выполнения перемешивания с пересечением полосы движения с 32-битными элементами,vpblendd
для смешивания с элементом0.0
, где ты хочешь это. - person Peter Cordes   schedule 23.05.2020gcc
похоже, нравится код в цикле. Не могли бы вы объяснить, почемуvpermd/vpblendd
было бы предпочтительнее? Агнер Фог и uops.info показываютvpalignr
быть быстрым, очевидно, это не считается инструкцией по пересечению полосы движения. - person EOF   schedule 23.05.2020vpermd
стоит столько же, сколькоvperm2f128
на оборудовании Intel, возможно, несколько меньше на Zen 1.vpblendd
составляет 1 мкоп для любого векторного порта ALU на Intel, поэтому это позволяет избежать потенциального узкого места при случайном перемещении портов изvperm2f128
+vpalignr
. vpalignr - это просто перетасовка на полосе, поэтому почему нам нужен vperm2f128 для его настройки. - person Peter Cordes   schedule 23.05.2020vpalignr
нахождение в полосе (для меня) совсем не очевидно, поскольку он перемещает данные с нижней полосы по крайней мере одного входа на верхнюю полосу выхода. - person EOF   schedule 23.05.2020palign
до 256 бит, и почему GCC нуженvperm2f128
. См. 256-битную диаграмму в felixcloutier.com/x86/palignr - person Peter Cordes   schedule 23.05.2020vblendps
: godbolt.org/z/RW7_ds, которые требуется вектор тасования (технически можно использовать тот же вектор для смешения). Это должно быть возможно только сvperm2f128
иvpalignr
(vperm2f128
может установить половину в 0) - не требуя вектора тасования, но две операции над p5. - person chtz   schedule 23.05.2020