Profile Guided Optimization).
Оптимизация профилей была впервые использована в конце 90-х годов исследовательскими группами Visual C и Microsoft. Тогда его проектировали под архитектуру Itanium. Затем PGO был включен в Visual Studio C/C++ 2005. Сегодня это основной процесс оптимизации, который значительно повышает производительность приложений Microsoft и других разработчиков.
В этом посте будет рассказано, как создавать более быстрые и высокопроизводительные нативные приложения.
Сначала давайте подробнее рассмотрим PGO, а затем воспользуемся примером (симуляция NBody), чтобы увидеть, как вы можете применить этот процесс оптимизации к своим приложениям, выполнив несколько простых шагов.
Для работы используйте исходный код из пример .
Для создания проекта вам понадобится DirectX SDK .
Как сделать нативное приложение быстрее
Традиционные компиляторы работают с оптимизацией, основанной на статических исходных файлах.Они анализируют текст исходного файла, но не учитывают введенные пользователями данные, которые просто невозможно узнать из кода.
Рассмотрим этот псевдокод:
При работе с функцией WhichBranchIsTaken компилятор не знает, насколько часто параметр «a» будет меньше параметра «b», и сколько раз будет применено условие «if» (то есть компилятор не может предсказать ветвления ).
При работе с функциями девиртуализации и switchCaseExpansion компилятор недостаточно знает о значениях *p и i, что делает невозможным оптимизацию девиртуализации и расширения параметров.
Эти проблемы становятся еще более выраженными, если мы подставляем данный фрагмент кода в разные модули (например, в разные объектные файлы), поскольку традиционные функции компиляции не могут быть оптимизированы для работы внутри исходных модулей.
Базовая модель компилятора и компоновщика не так уж и плоха, но в ней отсутствуют две основные функции оптимизации.
Во-первых, он не использует информацию, которую можно было бы получить, анализируя все исходные файлы (традиционные компиляторы оптимизируют только отдельные объектные файлы).
Во-вторых, он не оптимизируется на основе ожидаемого или профильного ответа приложения.
Первый недостаток можно исправить с помощью переключателя компилятора ( /ГЛ ) или переключатель компоновщика ( /ЛТКГ ), который выполняет полную оптимизацию программы и необходим для профильной оптимизации приложения.
После включения полной оптимизации программы вы можете применить оптимизацию профиля.
Давайте посмотрим на это более подробно.
PGO — это процесс оптимизации компилятора среды выполнения, который использует данные профиля, собранные при запуске критически важных или ресурсоемких пользовательских сценариев, для оптимизации приложения.
Оптимизация профиля имеет несколько преимуществ по сравнению с традиционной статической оптимизацией, поскольку она учитывает поведение приложения в рабочей среде.
Это позволяет оптимизатору выполнять оптимизацию скорости (для сценариев с частыми пользователями) или оптимизацию размера (для сценариев с редкими пользователями).
В результате код становится более лаконичным, что в конечном итоге повышает производительность приложения.
В настоящее время PGO можно использовать только в классических настольных приложениях и поддерживается на платформах x86 и x64. PGO — это трехэтапный процесс, как показано на рисунке выше.
- Первую стадию обычно называют этап инструментирования .
На этом этапе приложение собирается с заданным набором флагов компиляции.
В процессе сборки внутренний компилятор добавляет к сгенерированному коду тестовые инструкции (зонды), которые используются для записи обучающих данных, необходимых на следующем этапе.
Всего добавляется три типа проб (ввод функции, переход и значения).
Проверка ввода функции измеряет, как часто запрашивалась конкретная функция.
Зонд перехода позволяет узнать, сколько раз была достигнута определенная ветка кода.
Таким образом, на этапе обучения компилятор узнает, как часто «a > b» встречается во фрагменте кода, которыйBranchisTaken в данном сценарии обучения.
Датчик значений предоставляет данные для построения гистограммы значений.
Например, пробник значений, добавленный в фрагмент кода switchCaseExpansion, предоставит данные для построения гистограммы значений для случая переключения индексной переменной i. Получив в ходе обучения информацию о том, какие значения примет переменная «i», компилятор может оптимизировать под наиболее распространенные значения, а также такие функции, как switchCaseExpansion. Таким образом, в конце этапа мы будем иметь инструментированную версию приложения (с зондами) и пустой файл базы данных (.
pgd), который будет содержать информацию, полученную на следующем этапе.
- Этап обучения .
На этом этапе пользователь запускает инструментированную версию приложения и выполняет стандартные пользовательские сценарии, требующие высокой производительности.
На выходе получаются файлы .
pgc, содержащие информацию, относящуюся к различным пользовательским сценариям.
В процессе обучения информация проходит через зонды, добавленные на первом этапе.
Выходные данные — это имя_приложения!# файлов pgc (где имя_приложения — это имя приложения, а # — это единица плюс количество файлов «имя_приложения!#» pgc в выходном каталоге сборки).
- Последний этап PGO — оптимизация.
.
На этом этапе создается оптимизированная версия приложения.
Кроме того, информация из файлов pgc, полученная на этапе обучения, в фоновом режиме вводится в базу данных (файл .
pgd), созданную во время инструментирования.
Затем внутренний компилятор использует эту базу данных для дальнейшей оптимизации кода и создания еще лучшей версии приложения.
Фактически, первые две фазы могут быть опущены при построении последующих версий, и код может претерпевать существенные изменения по сравнению с версией, полученной после этапа обучения приложения.
В больших командах один разработчик может отвечать за запуск PGO и поддержку базы данных обучения (.
pgd) в репозитории исходного кода.
Другие разработчики могут синхронизировать свои репозитории кода с этой базой данных и использовать обучающие файлы для создания версий своих приложений, оптимизированных для PGO. После определенного количества перекомпиляций приложение будет окончательно оптимизировано.
Применение оптимизации профиля
Теперь, когда мы знаем немного больше об оптимизации профиля, давайте рассмотрим ее применение на конкретном примере.Оптимизацию профиля приложения можно выполнить с помощью Visual Studio или командной строки разработчика.
Ниже приведен пример работы в Visual Studio с приложением под кодовым названием «Nbody Simulation».
Если вы хотите узнать больше о PGO в командной строке, обратитесь к эти статьи .
Для начала загрузите решение в Visual Studio и выберите конфигурацию сборки для работы (т. е.
«Выпуск»).
Как уже говорилось выше, PGO состоит из трёх этапов: инструментирование, обучение и оптимизация.
Чтобы создать инструментированную версию приложения, щелкните правой кнопкой мыши по названию проекта («NBodyGravityCPU») и выберите раздел «Инструмент» в меню «Профильная управляемая оптимизация».
Инструментированная версия приложения будет создана в Visual Studio. После этого можно переходить к этапу обучения.
Запустите инструментированную версию приложения.
Для этого перейдите в меню «Оптимизация по профилю» и выберите «Запустить инструментированное/оптимизированное приложение».
В нашем случае приложение выполняется с максимально большим телом кода (15360), поскольку будет реализован стабильный пользовательский сценарий, требующий высокой производительности.
Как только два основных показателя производительности приложения, FPS (кадров в секунду) и GFlop, станут стабильными, вы можете закрыть приложение.
На этом этап обучения будет завершен, и полученные данные будут сохранены в файле .
pgc. По умолчанию файл .
pgc будет включен в вашу конфигурацию сборки, то есть в каталог «Выпуск».
Например, в результате этого обучения создается файл NBodyGravityCPU!1.pgc.
NBody Simulation — очень простое приложение, предназначенное исключительно для иллюстрации процесса PGO. В действительности может быть много возможных сценариев обучения приложениям.
В частности, обучение может проводиться в несколько этапов, разделенных по времени.
Лучший способ записать такие сценарии обучения — использовать команду pgosweep в командной строке разработчика после того, как инструментированная версия уже создана (например, в Visual Studio).
На заключительном этапе PGO создается оптимизированная версия приложения.
В меню «Оптимизация по профилю» выберите «Оптимизировать».
Будет создана оптимизированная версия приложения.
В журнале вывода сборки PGO вы увидите сводную информацию о выполненной операции.
Как упоминалось выше, информация из файлов .
pgc, полученная на этапе обучения, включается в базу данных .
pgd, которая затем используется внутренней матрицей оптимизации компилятора.
В большинстве случаев (за исключением небольших, быстрых приложений) критерий оптимизации скорости/размера определяется соотношением динамических инструкций для конкретной функции.
Функции с большим количеством инструкций (так называемые «горячие») оптимизируются по скорости, а функции с небольшим количеством инструкций (так называемые «холодные») оптимизируются по размеру.
Это практически все, что вам нужно, чтобы начать оптимизацию профилей в ваших приложениях.
Попробуйте использовать PGO для своих приложений и посмотрите результаты! И обязательно загляните в блог Инструменты разработчика , возможно, вы найдете там еще какие-нибудь интересные решения! Автор: Анкит Астхана ( Анкит Астхана ) — программный менеджер внутреннего компилятора Microsoft Visual C++.
Теги: #C++ #Visual Studio #оптимизация кода #visual studio 2012
-
Интервью Носика — Просто Подарок Какой-То
19 Oct, 24 -
Инстинктивный Страх Быть Взломанным
19 Oct, 24 -
Список Белорусских Социальных Сетей
19 Oct, 24 -
25 Способов Улучшить Ваш Сайт
19 Oct, 24 -
Новый Планшет Samsung Galaxy Tab 10.1
19 Oct, 24 -
Скрытые Деньги Во Фрилансе
19 Oct, 24