GCC Руководство для процессоров Ampere — CodesCode

Изучите, как эффективно использовать компилятор GCC для оптимизации приложений, работающих на процессорах Ampere.

Эта статья была изначально опубликована компанией Ampere Computing.

В этой статье описывается, как эффективно использовать параметры GNU Compiler Collection (GCC) для оптимизации производительности приложений на процессорах Ampere.

При попытке оптимизации приложения очень важно измерить, улучшает ли потенциальная оптимизация производительность. Это включает параметры компилятора. Использование продвинутых параметров компилятора может привести к лучшей производительности во время выполнения, однако это может потребовать больше времени компиляции, вызвать сложности при отладке и увеличить размер бинарного файла. Почему параметры компилятора влияют на производительность выходит за рамки этой статьи, хотя краткий ответ заключается в том, что генерация кода, современные архитектуры процессоров и их взаимодействие — очень сложные вещи! Важно отметить, что разные процессоры могут получать выгоду от разных параметров компилятора из-за различий в архитектуре компьютера и конкретной микроархитектуре. Повторное экспериментирование с оптимизациями — ключ к успешной оптимизации производительности.

Как измерить производительность приложения для определения факторов, ограничивающих его работу, а также стратегии оптимизации уже были рассмотрены в ранее опубликованных статьях. В статье The First 10 Questions to Answer While Running on Ampere Altra-Based Instances описывается, какие данные по производительности собирать, чтобы понять производительность всей системы. A Performance Analysis Methodology for Optimizing Ampere Altra Family Processors объясняет, как эффективно и эффективно оптимизировать с применением методики, основанной на данных.

В данной статье первоначально кратко описываются наиболее распространенные параметры GCC с описанием их влияния на приложения. Затем приводятся примеры использования параметров GCC для повышения производительности программного обеспечения для видеокодирования VP9 и базы данных MySQL на процессорах Ampere. Представленные стратегии успешно использовались для оптимизации другого программного обеспечения на процессорах Ampere.

Рекомендации GCC

Компилятор GCC предоставляет множество опций, которые могут улучшить производительность приложения. См. веб-сайт GCC для получения подробной информации. Чтобы сгенерировать код, воспользуйтесь всеми доступными возможностями производительности, предоставляемыми процессорами Ampere, используйте опцию gcc -mcpu.

Чтобы использовать опцию gcc -mcpu, установите модель CPU или позвольте GCC использовать модель CPU, основанную на машине, на которой выполняется GCC, с помощью -mcpu=native. Обратите внимание, что на устаревших системах, основанных на архитектуре x86, gcc -mcpu — это устаревший синоним для -mtune, тогда как gcc -mcpu полностью поддерживается на системах, основанных на архитектуре Arm. См. руководство от Arm по флагам компилятора для разных архитектур: -march, -mtune и -mcpu для получения более подробной информации.

В итоге, при возможности используйте только -mcpu и избегайте -march и -mtune при компиляции для архитектуры Arm. Ниже приведены примеры, демонстрирующие увеличение производительности при использовании опции gcc -mcpu с программным обеспечением для видеокодирования VP9.

Установка опции -mcpu:

  • -mcpu=ampere1: Генерируется код, который будет выполняться на процессорах AmpereOne. AmpereOne — это новое поколение процессоров для облачных решений от Ampere, предлагающее новые рекордные значения числа ядер и высокую производительность. Обратите внимание, что этот код может не работать на процессорах Ampere Altra и Ampere Altra Max. Эта опция была впервые доступна в GCC версии 12.1 и выше, а затем была обратно перенесена в GCC 10.5 и GCC 11.3.

  • -mcpu=neoverse-n1: Генерируется код, который будет выполняться на процессорах Ampere Altra, Ampere Altra Max, а также Ampere AmpereOne. Хотя эта опция поддерживается для кода, который будет выполняться на процессорах Ampere AmpereOne, она потенциально не использует все новые возможности производительности. Обратите внимание, что для возможности настройки под конкретный CPU на Ampere Altra и Ampere Altra Max необходима версия GCC 9.1 или выше.

  • -mcpu=native: Генерируется код, устанавливающий модель CPU на основе того, на какой машине выполняется GCC. Обратите внимание, что для возможности настройки под конкретный CPU на Ampere Altra и Ampere Altra Max необходима версия GCC 9.1 или выше.

Использование -mcpu=native потенциально проще в использовании, но имеет потенциальную проблему, если исполняемый файл, располитм на разных системах. Если сборка была выполнена на процессоре Ampere AmpereOne, код может не запуститься на процессоре Ampere Altra или Altra Max, потому что сгенерированный код может содержать инструкции Armv8.6+, поддерживаемые на процессорах Ampere AmpereOne. Если сборка была выполнена на процессоре Ampere Altra или Altra Max, GCC не воспользуется последними улучшениями производительности, доступными на процессорах Ampere AmpereOne. Это общая проблема при сборке кода для использования возможностей производительности любой архитектуры.

В следующей таблице приведены версии GCC, поддерживающие значения -mcpu для процессоров Ampere.

Процессор Значение -mcpu GCC 9 GCC 10 GCC 11 GCC 12 GCC 13
Ampere Altra neoverse-n1 ≥ 9.1 ALL ALL ALL ALL
Ampere Altra Max neoverse-n1 ≥ 9.1 ALL ALL ALL ALL
AmpereOne ampere1 N/A ≥ 10.5 ≥ 11.3 ≥ 12.1 ALL

Наши рекомендации – использовать опцию gcc -mcpu с соответствующим значением, описанным выше (-mcpu=ampere1, -mcpu=neoverse-n1 или -mcpu=native) с -O2, чтобы создать базовую основу для производительности, а затем исследовать дополнительные варианты оптимизации и измерять, улучшают ли различные опции производительность по сравнению с базовой основой.

Краткое описание общих опций GCC:

  • -mcpu Рекомендуется при сборке на процессорах Ampere для включения настройки и оптимизаций, специфических для процессора. (См. раздел “Настройка параметра -mcpu” выше для получения подробной информации.)

  • -Os Оптимизация для уменьшения размера кода, потенциально применима, если ваше приложение ограничено получением инструкций.

  • -O2 Стандартная оптимизация GCC, хорошая для использования в качестве базы для сравнения с другими опциями GCC.

  • -O3 Добавляет дополнительные оптимизации для создания более эффективного кода для циклов, полезно, если производительность вашего приложения определяется временем, затрачиваемым на циклы.

  • Оптимизация на основе профиля (PGO): -fprofile-generate и -fprofile-use. Генерируется профиль данных, который компилятор может использовать для принятия лучших решений по оптимизации, таких как инлайнинг, оптимизация циклов и ветвлений по умолчанию. Это считается продвинутой оптимизацией, так как требует изменений в системе сборки, см. ниже.

  • Оптимизация на уровне связывания (LTO): -flto. Включение оптимизаций на уровне связывания, позволяющее компилятору оптимизировать отдельные исходные файлы. Это позволяет функциям быть встроенными в разных исходных файлах среди других оптимизаций компилятора. Это также считается продвинутой оптимизацией и потенциально требует изменений в системе сборки. Эта опция увеличивает общее время сборки, что может быть значительным для больших приложений. Можно использовать LTO только на исходных файлах критических для производительности, чтобы потенциально сократить время сборки.

Case Study по кодированию видео с использованием VP9 и gcc -mcpu

VP9 – это формат видео-кодирования, разработанный Google. libvpx – это открытое программное обеспечение, являющееся референсной реализацией кодеков VP8 и VP9 от Google и Alliance for Open Media (AOMedia). libvpx обеспечивает значительное улучшение сжатия видео по сравнению с x264, однако требует дополнительного времени вычислений. Дополнительную информацию о VP9 и libvpx можно найти на Wikipedia.

В этом исследовании постановлены задачи основной сборки VP9 с использованием опции gcc -mcpu=native для повышения производительности. Как уже упоминалось ранее, используйте опцию -mcpu при компиляции на процессорах Ampere для настройки и оптимизации под конкретное CPU. Исходно libvpx собирается с использованием конфигурации по умолчанию, а затем повторно собирается с использованием -mcpu=native. Для оценки производительности VP9 использовался видеофайл 1080P, original_videos_Sports_1080P_Sports_1080P-0063.mkv из набора данных о пользовательских контентах YouTube’s User Generated Content Dataset. Для получения подробностей о том, как собрать ffmpeg и различные кодеки, включая VP9, для процессоров Ampere, ознакомьтесь с настройками ffmpeg и руководством по сборке от Ampere.

Сборка libvpx по умолчанию:

$ git clone https://chromium.googlesource.com/webm/libvpx$ cd libvpx/$ export CFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wimplicit-function-declaration -Wmissing-declarations -Wmissing-prototypes -Wuninitialized -Wunused -Wextra -Wundef -Wframe-larger-than=52000 -std=gnu89"$ export CXXFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdisabled-optimization -Wextra-semi -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wmissing-declarations -Wuninitialized -Wunused -Wextra -Wno-psabi -Wc++14-extensions -Wc++17-extensions -Wc++20-extensions -std=gnu++11 -std=gnu++11"$ ./configure$ make verbose=1 $ ./vpxenc --codec=vp9 --profile=0 --height=1080 --width=1920 --fps=25/1 --limit=100 -o output.mkv /home/joneill/Videos/original_videos_Sports_1080P_Sports_1080P-0063.mkv --target-bitrate=2073600 --good --passes=1 --threads=1 –debug

Оптимизация сборки libvpx с использованием -mcpu=native

$ # пересборка с -mcpu=native$ make clean$ export CFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wimplicit-function-declaration -Wmissing-declarations -Wmissing-prototypes -Wuninitialized -Wunused -Wextra -Wundef -Wframe-larger-than=52000 -std=gnu89"$ export CXXFLAGS="-mcpu=native -DNDEBUG -O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wdisabled-optimization -Wextra-semi -Wfloat-conversion -Wformat=2 -Wpointer-arith -Wtype-limits -Wcast-qual -Wvla -Wmissing-declarations -Wuninitialized -Wunused -Wextra -Wno-psabi -Wc++14-extensions -Wc++17-extensions -Wc++20-extensions -std=gnu++11 -std=gnu++11"$ ./configure $ make verbose=1 # проверка сборки на использование инструкции скалярного произведения sdot:$ objdump -d vpxenc | grep sdot | wc -l128$ ./vpxenc --codec=vp9 --profile=0 --height=1080 --width=1920 --fps=25/1 --limit=100 -o output.mkv /home/joneill/Videos/original_videos_Sports_1080P_Sports_1080P-0063.mkv --target-bitrate=2073600 --good --passes=1 --threads=1 --debug

Расследование с использованием Linux perf для измерения количества тактов центрального процессора в функциях, которые занимали больше всего времени, включает функции vpx_convolve8_horiz_neon и vpx_convolve8_vert_neon. Репозиторий git libvpx показывает, что эти функции были оптимизированы Arm для использования инструкции Armv8.6-A USDOT (смешанное умножение) supported Armv8.6-A процессорами.

Количество тактов центрального процессора, затраченных на vpx_convolve8_horiz_neon, было сокращено с 6.07E+11 до 2.52E+11 с использованием gcc -mcpu=native для включения оптимизации смешанного умножения на процессоре Ampere Altra, что привело к сокращению количества циклов на 2.4 раза.

Для vpx_convolve8_vert_neon количество циклов центрального процессора было сокращено с 2.46E+11 до 2.07E+11, что составляет сокращение на 16%.

В целом, использование опции -mcpu=native для включения инструкции смешанного умножения ускорило транскодирование файла original_videos_Sports_1080P_Sports_1080P-0063.mkv на 7% на процессоре Ampere Altra, улучшив производительность приложения. В таблице ниже приведены данные, собранные с помощью утилитов perf record и perf report для измерения циклов центрального процессора и выполненных инструкций.

Конфигурация сборки Символ Циклы(%) Циклы Инструкции(%) Инструкции
Сборка по умолчанию vpx_convolve8_horiz_neon 8.72 6.07E+11 7.52 1.13E+12
vpx_convolve8_vert_neon 3.53 2.46+E11 2.51 3.78E+11
Вся программа 100 6.97E+10 100 1.48E+11
-mcpu=native vpx_convolve8_horiz_neon 3.89 2.52E+11 3.87 5.71E+11
vpx_convolve8_vert_neon 3.19 2.07+E11 3.29 4.86E+11
Вся программа 100 6.48E+10 100 1.48E+11

Оптимизация с помощью профилирования GCC

В этом разделе рассматривается обзор оптимизации с помощью профилирования GCC (PGO) и исследование случая оптимизации MySQL с PGO. Оптимизация с использованием профилирования позволяет GCC принимать более точные решения об оптимизации, включая оптимизацию ветвлений, переупорядочивание блоков кода, инлайнинг функций и оптимизацию циклов с помощью разворачивания циклов, частичного разворачивания циклов и векторизации. Использование PGO требует изменения среды сборки для выполнения трехчастной сборки.

  1. Собрать приложение с оптимизацией с помощью профилирования, gcc -fprofile-generate.
  2. Выполнить приложение на представительных рабочих нагрузках для создания профиля данных.
  3. Пересобрать приложение с использованием профильных данных, gcc -fprofile-use.

Одной из проблем использования PGO является чрезвычайно высокая нагрузка на производительность на шаге 2. Из-за медленной производительности при выполнении приложения, собранного с помощью gcc -fprofile-generate, может быть нецелесообразно запускать его на системах, работающих в производственной среде. См. раздел Параметры инструментации программы в руководстве GCC для сборки приложений с инструментацией времени выполнения и раздел Параметры, управляющие оптимизацией для пересборки с использованием сгенерированных профильных данных для получения дополнительной информации.

Как описано в руководстве GCC, -fprofile-update=atomic рекомендуется для многопоточных приложений и может повысить производительность путем сбора улучшенных профильных данных.

Когда использовать PGO?

С помощью PGO GCC может лучше оптимизировать приложения, предоставляя дополнительную информацию, такую как измерение взятых и невзятых ветвей и измерение количества итераций в цикле. PGO – это полезная оптимизация, которую стоит попробовать, чтобы увидеть, улучшает ли она производительность. Производительности, в которых PGO может помочь, включают приложения с значительным процентом неправильных предсказаний ветвей, которые можно измерить с помощью утилиты perf для чтения счётчика юнита мониторинга производительности (PMU) CPU BR_MIS_PRED_RETIRED. Большое количество неправильных предсказаний ветвей приводит к высокому проценту зависаний в передней части, который можно измерить с помощью счетчика PMU STALL_FRONTEND. Приложения с высокой частотой промахов L2-кеша команд также могут получить пользу от PGO, возможно, связанной с ошибочно предсказанными ветвлениями. В общем, высокий процент неправильных предсказаний ветвей, зависания передней части ЦП и промахи L2-кеша команд являются производительностными характеристиками, где PGO может повысить производительность.

MySQL база данных GCC PGO исследование

MySQL является самой популярной в мире свободной базой данных и из-за огромного размера бинарного файла MySQL является идеальным кандидатом для использования оптимизации GCC PGO. Без информации PGO GCC невозможно правильно предсказать выполнение различных кодовых путей. Использование PGO существенно снижает количество неправильных предсказаний ветвей, частоту промахов L2 кеша команд и зависания передней части ЦП на процессоре Ampere Altra Max.

Подводя итоги, как MySQL оптимизируется с использованием GCC PGO:

  1. Используется sysbench для оценки производительности MySQL
  2. Обучается GCC PGO с помощью набора тестов MySQL MTR (mysql-test-run)
  3. Тесты oltp_point_select и oltp_read_only из sysbench используются для измерения производительности с сборкой PGO по сравнению с обычной сборкой
  4. Количество используемых потоков варьируется от 1 до 1024, что дает среднее ускорение в 29% для теста oltp_point_select и 20% для теста oltp_read_only на процессоре Ampere Altra Max M128-30
  5. При 64 потоках PGO повышает производительность на 32%, улучшая пропускную способность MySQL

Дополнительные сведения можно найти на сайте разработчика Ampere Developer в руководстве по настройке MySQL – MySQL Tuning Guide.

Итог

Оптимизация приложений требует экспериментов с различными стратегиями, чтобы определить, что работает лучше всего. В этой статье содержатся рекомендации для разных оптимизаций компилятора GCC для создания высокопроизводительных приложений, работающих на процессорах Ampere. Она подчеркивает использование опции -mcpu как самого простого способа создания кода, использующего все возможности, поддерживаемые процессорами Ampere Cloud Native. Две исследовательские работы, посвященные базе данных MySQL и видеокодировщику VP9, демонстрируют использование опций GCC для оптимизации этих приложений, где производительность имеет важное значение.

Разработанные для устойчивого облачного вычисления, первые процессоры Cloud Native от Ampere обеспечивают предсказуемую высокую производительность, масштабируемость платформы и непревзойденную энергоэффективность в отрасли. Мы приглашаем вас узнать больше о наших усилиях для разработчиков и найти лучшие практики на сайте developer.amperecomputing.com и принять участие в обсуждении на community.amperecomputing.com.

Поделиться статьей


Leave a Reply

Your email address will not be published. Required fields are marked *