Что теряется при переходе с AVX512 на Intel Xeon Phi на AVX2 на Intel i5-8259U? - PullRequest
1 голос
/ 10 июня 2019

Пытаясь пройти курс на Coursera , я попытался оптимизировать пример кода C ++ для моего Intel i5-8259U ЦП, который, я считаю, поддерживает набор инструкций AVX2 SIMD.Теперь AVX2 предоставляет 16 регистров на ядро ​​(называемые YMM0, YMM1, ..., YMM15) шириной 256 бит, что означает, что каждый может обрабатывать до 4 чисел с плавающей запятой двойной точности одновременно.Использование AVX2 инструкций SIMD должно оптимизировать мой код, чтобы он выполнялся в 4 раза быстрее по сравнению со скалярными инструкциями.

В связанном курсе вы можете попробовать запустить тот же код для числовой интеграции на процессоре Intel Xeon Phi 7210 (Knights Landing), который поддерживает AVX512, который использует регистры шириной 512 бит.Это означает, что мы должны ожидать ускорения операций с двойной точностью в 8 раз. Действительно, код, используемый инструктором, получает оптимизацию до коэффициента 14, что составляет почти 173% от 8. Дополнительная оптимизация происходит из-за OpenMP.

Чтобы запустить тот же код на моем процессоре, я изменил только флаг оптимизации, передаваемый компилятору Intel: вместо -xMIC-AVX512 я использовал -xCORE-AVX2.Ускорение, которое я получил, составляет всего 2 раза, что является ничтожным 50% ожидаемого ускорения только из-за SIMD-векторизации на 256-битных регистрах.Сравните эти 50% с 173%, полученными на процессоре Intel Xeon Phi.

Почему я вижу такую ​​резкую потерю производительности, просто переходя с AVX512 на AVX2?Конечно, здесь есть что-то кроме оптимизации SIMD.Чего мне не хватает?


PS Вы можете найти ссылочный код в папке integral/solutions/1-simd/ здесь .

1 Ответ

4 голосов
/ 10 июня 2019

TL: DR: KNL (Knight's Landing) только хорошо работает с кодом, специально скомпилированным для него, и, таким образом, получает гораздо большее ускорение, потому что спотыкается из-за плохо работающего «универсального»code.

Coffee Lake ускоряется только в 2 раза со 128-битного SSE2 до 256-битного AVX, оптимально выполняя как «универсальный», так и целевой код.

Основные процессоры, такие как Coffee Lake, - одиниз целей, которые заботятся о «общей» настройке в современных компиляторах, и они не имеют много слабых мест в целом.Но КНЛ нет;ICC без каких-либо опций не заботится о KNL


Вы предполагаете, что базовая линия для ваших ускорений составляет скаляр .Но без каких-либо опций, таких как -march=native или -xCORE-AVX2, компилятор Intel (ICC) все равно будет автоматически векторизоваться с SSE2, потому что это базовый показатель для x86-64.

-xCORE-AVX2 не включает авто-векторизацию, он просто дает векторизации еще больше инструкций для игры.Уровень оптимизации (включая авто-векторизацию) контролируется -O0 / -O2 / -O3, а для FP - строгим и быстрым fp-model.Компилятор Intel по умолчанию использует полную оптимизацию с -fp-model fast=1 (на один уровень ниже fast=2), так что это что-то вроде gcc -O3 -ffast-math.

Но без дополнительных опций он может использовать только базовый набор инструкций, который дляx86-64 это SSE2.Это все же лучше, чем скаляр.

SSE2 использует 128-битные регистры XMM для упакованной двойной математики с той же пропускной способностью, что и AVX (на вашем i5 Coffee Lake), но вдвое меньше работы на инструкцию .(И у него нет FMA, поэтому компилятор не мог заключить какие-либо операции + добавления в вашем источнике в инструкции FMA, как это могло бы быть с AVX + FMA).

Так что фактор2 Ускорение на вашем процессоре Coffee Lake - это именно то, что вы должны ожидать для простой проблемы, которая является просто узким местом в пропускной способности векторного мульти / добавления / FMA SIMD (не память / кэш или что-либо еще).

Ускорение зависитна то, что делает ваш код.Если вы ограничены в пропускной способности памяти или кэша, более широкие регистры лишь немного помогают лучше использовать параллелизм памяти и поддерживать ее насыщенность.

А AVX + AVX2 добавляет более мощные тасовки, смеси и другие интересные вещи, но для простых задачс чистой вертикальной SIMD, которая не помогает.


Таким образом, реальный вопрос - Почему AVX512 помогает более чем в 4 раза по KNL? 8 double элементов на инструкцию AVX512 SIMDпри высадке Найта, по сравнению с 2 с SSE2, ожидаемое ускорение в 4 раза, если бы пропускная способность команд была такой же.Предполагая, что общее количество команд было идентичным с AVX512.(Но это не так: при той же развертке цикла количество векторной работы на цикл увеличивается с увеличением векторов и других факторов.)

Трудно сказать точно, не зная, каким исходным кодом вы быликомпилирование.AVX512 добавляет некоторые функции, которые могут помочь сохранять инструкции, такие как операнды источника широковещательной памяти вместо того, чтобы требовать отдельной широковещательной загрузки в регистр.

Если ваша проблема связана с каким-либо делением , KNL работает очень медленноFP-деление с полной точностью, и обычно следует использовать инструкцию приближения AVX512ER (28-битная точность) + итерация Ньютона-Рафсона (пара FMA + mul), чтобы удвоить это значение, давая почти полное double(53-битное значение, включая 1 неявный бит).-xMIC-AVX512 включает AVX512ER и устанавливает параметры настройки таким образом, чтобы ICC фактически выбрал его использование.

(В отличие от этого, пропускная способность 256-разрядного деления Coffee Lake AVX ничуть не лучше, чем пропускная способность 128-разрядного деления в два разаза цикл, но без AVX512ER не существует эффективного способа использования Newton-Raphson для double).См. деление с плавающей точкой против умножения с плавающей точкой - числа Скайлэйка относятся к вашему Coffee Lake.


AVX / AVX512 может избежать дополнительных movaps инструкций для копирования регистров , что очень помогает для KNL (каждая инструкция, которая не является mul / add / FMA, требует пропускной способности FP, потому что она имеет 2- FMA с тактовой частотой, но только максимальная пропускная способность команд по 2 такта).(https://agner.org/optimize/)

KNL основан на маломощном ядре Silvermont (именно так они устанавливают так много ядер на один чип).

В отличие от этого, у Coffee Lake гораздо более мощный фронт-конечная и внутренняя пропускная способность выполнения: в стойле имеется 2 FMA / мул / сложение на тактовую частоту, но 4 на общую тактовую пропускную способность, поэтому есть место для выполнения некоторых не-FMA инструкций без потери пропускной способности FMA.


Другие замедления при выполнении инструкций SSE / SSE2 на KNL (Xeon Phi)

KNL создан специально для запуска кода AVX512. Они не тратят впустую транзисторы, что делает его эффективным для выполнения устаревшего кода, который не был скомпилированспециально для него (с -xMIC-AVX512 или -march=knl).

Но ваше Coffee Lake - это основное ядро ​​настольного компьютера / ноутбука, которое должно быстро запускать любые прошлые или будущие двоичные файлы, включая код, который использует только «устаревшее»«Кодировки инструкций SSE2, а не AVX.

Инструкции SSE2, которые записывают регистр XMM, оставляют верхние элементы соответствующего регистра YMM / ZMMбез изменений.(Регулятор XMM - это младшие 128 битов полного векторного регистра).Теоретически это создаст ложную зависимость при запуске устаревших инструкций SSE2 на процессоре, который поддерживает более широкие векторы.(Основные процессоры Intel, такие как семейство Sandybridge, избегают этого с помощью смены режимов или фактических ложных зависимостей Skylake, если вы не используете vzeroupper правильно. См. Почему этот код SSE в 6 раз медленнее без VZEROUPPER на Skylake? для сравнения 2 стратегий).

KNL действительно , по-видимому, имеет способ избежать ложных зависимостей: согласно тестированию Агнера Фога ( в его руководстве по микроархам )он описывает это как частичное переименование регистров, которое делает семейство P6, когда вы записываете в целочисленные регистры, такие как AL.Вы получаете только частичный регистр, когда читаете полный регистр.Если это верно, то код SSE2 должен нормально работать на KNL, потому что нет кода AVX, читающего регистры YMM или ZMM.

(Но если бы были ложные зависимости, movaps xmm0, [rdi] в цикле, возможно, пришлось бы ждатьдо тех пор, пока последняя инструкция для записи xmm0 в предыдущей итерации не будет завершена. Это лишит KNL возможности выполнять не по порядку выполнение, чтобы перекрывать независимую работу между циклами итераций и скрывать нагрузку + задержка FP.)


Существует также возможность декодирования остановок на KNL при запуске устаревших инструкций SSE / SSE2: он останавливается на инструкциях с более чем 3 префиксами, включая 0F экранирующих байтов.Так, например, любая инструкция SSSE3 или SSE4.x с префиксом REX для доступа к r8..r15 или xmm8..xmm15 вызовет задержку декодирования от 5 до 6 циклов.

Но этого не произойдет, еслиВы пропустили все опции -x / -march, потому что SSE1 / SSE2 + REX все еще в порядке.Просто (опционально REX) + 2 других префикса для таких инструкций, как 66 0F 58 addpd.

См. Руководство по микроарху Agner Fog в главе KNL: 16.2 извлечение и декодирование инструкций .


OpenMP - если вы смотрите на OpenMP для использования нескольких потоков, очевидно, что KNL имеет гораздо больше ядер.

Но даже в пределах одного физического ядра,KNL имеет 4-х стороннюю гиперпоточность как еще один способ (кроме exec-порядка exec), чтобы скрыть высокую задержку своих инструкций SIMD.Например, задержка FMA / add / sub составляет 6 циклов в KNL против 4 в Skylake / Coffee Lake.

Таким образом, разбиение проблемы на несколько потоков может иногда значительно увеличить использование каждого отдельного ядра в KNL.Но в таком крупномядерном центральном процессоре, как Coffee Lake, его огромные возможности неупорядоченного выполнения уже могут находить и использовать весь параллелизм на уровне команд во многих циклах, даже если тело цикла выполняет цепочку действий с каждым независимым входом..

...