Передача 1-в-4 и уменьшение 4-в-1 в AVX-512 - PullRequest
0 голосов
/ 12 октября 2018

Мне нужно выполнить следующие две операции:

float x[4];
float y[16];

// 1-to-4 broadcast
for ( int i = 0; i < 16; ++i )
    y[i] = x[i / 4];

// 4-to-1 reduce-add
for ( int i = 0; i < 16; ++i )
    x[i / 4] += y[i];

Какая будет эффективная реализация AVX-512?

1 Ответ

0 голосов
/ 13 октября 2018

Для уменьшения-добавления просто делайте тасования и добавления в линию (vmovshdup / vaddps / vpermilps imm8 / vaddps), как в Самый быстрый способ сделать горизонтальную векторную сумму с плавающей точкой на x86 для получения горизонтальной суммы в каждой 128-битной полосе, а затем vpermps для перетаскивания нужных элементов в низ.Или vcompressps с постоянной маской, чтобы сделать то же самое, необязательно с назначением памяти.

После упаковки в один вектор у вас есть обычное SIMD 128-битное добавление.

Если ваши массивы на самом деле больше 16, вместо vpermps вы можете vpermt2ps взять каждый 4-й элемент из каждого из двух векторов-источников, настроив вас на выполнение += часть с x[] 256-битными векторами.(Или снова объединить с другим тасованием в 512-битные векторы, но это, вероятно, станет узким местом для пропускной способности тасования в SKX).

В SKX vpermt2ps - это всего лишь один моп, с пропускной способностью 1c / задержкой 3c,так что это очень эффективно для того, насколько это мощно.На KNL он имеет пропускную способность 2c, хуже, чем vpermps, но, возможно, все же стоит.(KNL не имеет AVX512VL, но для добавления к x[] с 256-битными векторами вы (или компилятор) можете использовать AVX1 vaddps ymm, если хотите.)

См. https://agner.org/optimize/для таблиц инструкций.


Для нагрузки:

Это делается внутри цикла или многократно?(т. е. можете ли вы сохранить вектор управления тасованием в регистре? Если это так, вы можете

  • сделать 128-> 512 трансляций с VBROADCASTF32X4 (один моп дляпорт загрузки).
  • выполните перемешивание на линии с vpermilps zmm,zmm,zmm для широковещательной передачи различного элемента в каждой 128-битной полосе. (Должен быть отделен от широковещательной загрузки, посколькуисточник памяти vpermilps может иметь источник m512 или m32bcst (инструкции обычно имеют гранулярность широковещательной передачи памяти = размер элемента, к сожалению, в некоторых случаях, таких как этот, когда это совсем не полезно. И vpermilpsпринимает операнд памяти как операнд памяти, а не исходные данные.)

Это немного лучше, чем vpermps zmm,zmm,zmm, потому что у перемешивания есть задержка в 1 цикл вместо 3 (вкл.Skylake-avx512).

Даже вне цикла загрузка вектора с произвольным управлением все еще может быть лучшим выбором.

...