Использование инструкций по смешиванию в Intel Intrinsics (AVX)
У меня вопрос по AVX _mm256_blend_pd
функция.
Я хочу оптимизировать свой код, в котором я активно использую _mm256_blendv_pd
функция. К сожалению, это имеет довольно высокую задержку и низкую пропускную способность. Эта функция принимает на вход три__m256d
переменные, где последняя представляет собой маску, которая используется для выбора из первых двух переменных.
Нашел другую функцию (_mm256_blend_pd
), который принимает битовую маску вместо __m256d
переменная как маска. Когда маска статична, я могу просто передать что-то вроде 0b0111
взять первый элемент из первой переменной и последние 3 элемента из второй переменной. Однако в моем случае маска вычисляется с использованием_mm_cmp_pd
функция, которая возвращает __m256d
переменная. Я узнал, что могу использовать_mm256_movemask_pd
чтобы вернуть int из маски, однако при передаче этого в функцию _mm256_blend_pd
Я получаю ошибку error: the last argument must be a 4-bit immediate
.
Есть ли способ передать это целое число, используя его первые 4 бита? Или есть еще одна функция, похожая на movemask, которая позволила бы мне использовать_mm256_blend_pd
? Или есть другой подход, который я могу использовать, чтобы избежать использования cmp, movemask и blend, который был бы более эффективным для этого варианта использования?
1 ответ
_mm256_blend_pd
является внутренним для vblendpd
который принимает свой управляющий операнд как непосредственную константу, встроенную в машинный код инструкции. (Это то, что означает "немедленный" в терминологии ассемблера / машинного кода.)
В терминах C++ контрольный аргумент должен быть constexpr
поэтому компилятор может встроить его в инструкцию во время компиляции. Вы не можете использовать его для смешивания переменных времени выполнения.
К сожалению, инструкции по смешиванию переменных, такие как vblendvpd
медленнее, но на Skylake они "всего" 2 мупа с задержкой в 1 или 2 цикла (в зависимости от того, через какой вход вы измеряете критический путь). (uops.info). А на Skylake эти мопы могут работать на любом из трех векторных портов ALU. (Хуже на Haswell/Broadwell, однако, ограничен только портом 5, конкурируя за это с перемешиванием). Дзен даже может управлять ими как единым целым.
Нет ничего лучше для общего случая, пока AVX512 не выполнит маскирование первоклассной операции, которую вы можете выполнить как часть других инструкций, и не предоставит нам инструкции по однократному смешиванию, такие как vblendmpd ymm0{k1}, ymm1, ymm2
(смешайте согласно регистру маски).
В некоторых особых случаях вы можете с пользой _mm256_and_pd
условно обнулить вместо смешивания, например, обнулить вход перед add
вместо смешивания после.
TL:DR: _mm256_blend_pd
позволяет использовать более быструю инструкцию для особого случая, когда элемент управления является константой времени компиляции.