Использование инструкций по смешиванию в 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позволяет использовать более быструю инструкцию для особого случая, когда элемент управления является константой времени компиляции.

Другие вопросы по тегам