Вероятно, ваша лучшая ставка для векторизации этого может быть с vpackssdw
/ vpackuswb
и vpermd
как исправление пересечения полосы после пакета в полосе.
_mm256_srli_epi32
, чтобы сместить показатель степени (и знаковый бит) в нижнюю часть каждого 32-разрядного элемента.Логический сдвиг оставляет неотрицательный результат независимо от знакового бита. - Затем упаковывает пары векторов до 16-бит с помощью
_mm256_packs_epi32
(знаковый вход, знаковая насыщенность выхода). - Затем маскирует знаковый бит , оставляя 8-битную экспоненту.Мы ждем до сих пор, поэтому мы можем сделать 16x
uint16_t
элементов на инструкцию вместо 8x uint32_t
.Теперь у вас есть 16-битные элементы, содержащие значения, которые помещаются в uint8_t
без переполнения. - Затем упакуйте пары векторов до 8-бит с помощью
_mm256_packus_epi16
(вход со знаком, без знака насыщенность выхода).Это действительно важно, packs
будет обрезать некоторые допустимые значения, потому что ваши данные используют полный диапазон uint8_t
. - VPERMD , чтобы перетасовать восемь 32-битных фрагментов этого вектора, которые пришлис каждой дорожки 4х 256-битных входных векторов.Точно такой же
__m256i lanefix = _mm256_permutevar8x32_epi32(abcd, _mm256_setr_epi32(0,4, 1,5, 2,6, 3,7));
shuffle, как и в Как преобразовать 32-битный float в 8-битный символ со знаком? , который делает тот же пакет после использования преобразования FP-> int вместо shift-shift для захватаполе экспоненты.
Для каждого вектора результатов у вас есть 4x load + shift (vpsrld ymm,[mem]
, мы надеемся), 2x vpackssdw
shuffles, 2x vpand
mask, 1x vpackuswb
и1x vpermd
.Это 4 шаффла, поэтому лучшее, на что мы можем надеяться на Intel HSW / SKL, - это 1 вектор результата на 4 такта.(Ryzen имеет лучшую пропускную способность, кроме vpermd
, что дорого.)
Но это должно быть достижимо, так что в среднем 32 байта ввода / 8 байтов вывода за такт.
10 полных векторных ALU-мопов (включая нагрузку с микроплавлением + ALU), и 1 хранилище должно быть в состоянии выполнить в это время.У нас есть место для 16 полных мопов, включая накладные расходы на петли, прежде чем внешний интерфейс станет худшим узким местом, чем тасования.
обновление: упс, Я забыл сосчитать, смещая показатель степени;это займет дополнительно add
.Но вы можете сделать это после упаковки до 8-битного. (и оптимизировать его до XOR).Я не думаю, что мы можем оптимизировать это или что-то еще, например, замаскировать знаковый бит.
С AVX512BW вы можете сделать байтовую гранулярность vpaddb
, чтобы разбить, с нулевым маскированием, чтобыОбнулить старший байт каждой пары.Это сложило бы смещение в 16-битное маскирование.
AVX512F также имеет vpmovdb
32-> 8-битное усечение (без насыщения),но только для одиночных входов.Таким образом, вы получите один 64-битный или 128-битный результат из одного входного 256 или 512-битного вектора с 1 случайным числом + 1 добавлением на вход вместо 2 + 1 случайных чисел + 2 с нулевой маской vpaddb
на каждый входной вектор.(Оба требуют сдвига вправо для каждого входного вектора, чтобы выровнять 8-битное поле экспоненты с байтовой границей внизу двойного слова)
С AVX512VBMI, vpermt2b
позволит нам получить байты из 2 входных векторов.Но на CannonLake это стоит 2 мопа, поэтому полезно только для гипотетических будущих процессоров, если оно станет дешевле.Они могут быть старшим байтом слова, поэтому мы могли бы начать с vpaddd
вектора до самого смещения влево на 1. Но мы, вероятно, лучше всего с левым сдвигом, потому что кодировка EVEX vpslld
или vpsrld
может извлекать данные из памяти с немедленным счетом сдвига, в отличие от кодировки VEX.Надеемся, что мы получим один микросинхронизированный uop load + shift для экономии полосы пропускания внешнего интерфейса.
Другой вариант - shift + blend, что приводит к получению результатов с чередованием байтов, которые болеедорого исправить, если только вы не возражаете против этого заказа.
А для смешивания байтовой гранулярности (без AVX512BW) требуется vpblendvb
, что составляет 2 моп.(А на Haswell работает только на 5-м порту, что потенциально является огромным узким местом. На SKL это 2 моп для любого векторного порта ALU.)