Три этапа подготовки к оптимизации параллельных программ

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

  • Первый этап: Выбор методики оптимизации. Современные практики помогут вам разумно планировать процесс и оставаться в рамках плана.
  • Второй этап: Создание подходящей рабочей задачи (workload). Правильный объем работы для тестирования приложения до и после оптимизации позволяет оценить результаты проделанной работы.
  • Третий этап: Построение тестового окружения (test environment). Правильное тестовое окружение позволяет точно предсказать, как ваше приложение будет работать в реальных условиях.

В совокупности эти три этапа помогают разработчику эффективно оптимизировать программы и использовать постоянно возрастающее число процессорных ядер.

Первый этап: выбор методики оптимизации

Самая важная вещь, о которой нужно помнить, приступая к оптимизации приложения, - это необходимость систематического подхода. Это означает, что нужно придерживаться научного метода, а также планировать свои действия и четко следовать утверждённому плану.

Грамотное начало – половина успеха

От момента первого обсуждения плана и до момента, когда вы решите, что все поставленные цели достигнуты, будет полезно соблюдать следующие несколько общих рекомендаций:

  • Ставьте цели и выбирайте соответствующую методику их достижения. Оптимизация – трудоемкий и иногда затратный процесс, и вам необходимо понимать, чего вы хотите достичь, чтобы потом понять, что вы достигли цели. Например, целью может быть достижение определенного уровня загрузки каждого ядра процессора или улучшение многопоточности, чтобы новая функция могла выполняться в реальном времени.
  • Оценивайте влияние каждого вносимого изменения. Подходящая рабочая задача (о ней речь пойдет ниже) позволяет измерять полученный результат по мере продвижения работы, и вы сможете точно выяснить, каков результат каждого вносимого изменения.
  • Ведите дневник. Записывайте все, что вы делаете с программой, а также причины таких действий. Заметки, сделанные во время работы над проектом, являются основой для базы знаний (пусть и неформальной), которая позволит сделать ваш следующий проект более успешным. Эти заметки должны включать все комментарии по проблемам, возникшим, например, при выборе рабочей задачи, и методах их преодоления.

Определение шагов

Вооружившись этими правилами, можно приступить к разработке методики, которая подскажет, какие изменения необходимо сделать, затем внести эти изменения и оценить их влияние на производительность приложения. Здесь нужно, в первую очередь, понимать, что это повторяющийся, цикличный процесс. Структура процесса показана на Схеме 1. На каждой последовательности шагов (один полный цикл) производится разработка, внедрение и проверка одного (и только одного) изменения в коде приложения:

  • Сбор данных о производительности. Первый шаг каждого повторяющегося процесса – это запуск рабочей задачи и измерение производительности с помощью подходящих метрик (рабочие задачи и метрики будут обсуждаться ниже). На данном этапе в оценке поведения потоков может помочь Intel® Concurrency Checker, о котором речь также пойдет ниже.
  • Анализ полученных данных и определение проблем. На этом этапе нам нужно определить возможности для улучшения. Для этого зачастую используются такие средства, как Intel® VTune Performance Analyzer, который показывает, где больше всего расходуется процессорное время, или Intel® Thread Profiler, определяющий неэффективную работу потоков.
  • Разработка альтернатив для решения проблемы. Для каждой проблемы существует решение. На данном этапе ищется решение, способное устранить возникшую проблему.
  • Внесение улучшений. Когда вы определитесь с планом изменений и занесёте в протокол проекта соответствующую запись, внесите необходимые изменения в код.
  • Тестирование результата. Соберите необходимые данные и сравните их с базовыми измерениями, тщательно обдумайте результаты и, при необходимости, вернитесь назад.


Схема 1: Замкнутый цикл оптимизации производительности

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

Чего делать не нужно

Перед тем, как закончить этот раздел, расскажем о нескольких ловушках, которых нужно остерегаться:

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

Software Optimization Cookbook, Second Edition – это обновленная версия ставшей уже классикой работы четырех инженеров Intel, которая поможет вам выстроить успешную методологию увеличения производительности.


Второй этап: выбор подходящей рабочей задачи

Методика улучшения производительности, спланированная нами в предыдущем разделе, нуждается еще в одном ключевом ингредиенте: рабочей задаче (workload). Рабочая задача находится в самом сердце процесса оптимизации, и правильный выбор рабочей задачи имеет ключевое значение для успеха проекта. Ее назначение – дать приложению конкретный объем работы, чтобы можно было точно измерить влияние оптимизации.

Выбор рабочей задачи – личное дело каждого

Когда дело доходит до выбора рабочей задачи, то тут на вкус и цвет товарищей нет. Многие организации-разработчики просят инженеров Intel прислать им рабочую задачу, которую они могли бы использовать в процессе оптимизации. К сожалению, этот подход нельзя считать верным, потому что выбор рабочей задачи очень сильно зависит от приложения. Рабочая задача должна адекватно загружать тестируемое приложение (см. характеристики эффективной рабочей задачи в следующем разделе).

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

Рабочие задачи бывают разные, от простых до очень сложных. Например, рабочая задача для тестирования производительности утилиты сжатия файлов может быть простым набором файлов, созданных в популярном офисном пакете. В этом случае файлы должны включать разные типы и размеры, количество файлов должно быть достаточно велико, чтобы время обработки позволяло выяснить различия при прогоне тестов.

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


Четыре характеристики эффективной рабочей задачи

Правильно подобранная рабочая задача должна иметь следующие характеристики:

  • Измеряемость. Должен быть выбран правильный, достоверный метод измерения производительности приложения при прогоне рабочей задачи. Используемые метрики зависят от типа тестируемого приложения. Например, игра может использовать показатель частоты фреймов в секунду. Программа электронной коммерции – количество транзакций в секунду. Сетевой фильтр – количество пакетов в секунду.
  • Повторяемость. В одних и тех же условиях рабочая задача должна каждый раз давать, по возможности, одни и те же результаты. Возможны некоторые вариации из-за таких неконтролируемых эффектов, как состояние кэша, работа фоновых задач операционной системы, но они должны быть настолько малы, чтобы не заглушать собой результаты тестирования. Для минимизации посторонних эффектов можно отключить антивирус и брандмауэр, а также увеличить размер тестовой рабочей задачи и длительность теста.
  • Статичность. Измерения, связанные с конкретной рабочей задачей, не должны меняться со временем. Примером этого может служить случай, когда тестовый процесс делает много операций файлового ввода-вывода, забивая под завязку дисковый накопитель, и операции чтения и записи начинают в конце отнимать существенно больше времени, снижая производительность тестируемой программы независимо от вносимых в рамках оптимизации изменений.
  • Репрезентативность. Выполняемая рабочая задача должна представлять собой типическую стрессовую задачу для системы, работающей в нормальном режиме. Она должна задействовать как можно большую часть кода и при этом представлять собой обычный сценарий использования, в отличие от, например, акцентирования на одной отдельной части приложения, по поводу которой разработчик решил, что она важнее всего.

Чего делать не нужно

После того, как мы обсудили базовые характеристики подходящей рабочей задачи, можно рассмотреть противоположный случай, чтобы закрепить понимание. Ниже даны примеры общих ошибок, которые могут допустить разработчики:

  • Не стоит выбирать слишком маленькие задачи. Если объем тестовой задачи слишком мал, то очередные изменения могут не проявиться. Например, если тестовая задача сначала выполняется за 10 секунд, а после внесения изменений за 9,5, то такую разницу трудно отследить с помощью секундомера, хотя это составляет пятипроцентную прибавку производительности. Отметим, что в некоторых случаях можно выйти из положения, подсчитывая, сколько раз тестовая задача выполняется за заданный промежуток времени, а не измеряя время ее однократного выполнения.
  • Не ограничивайтесь подмножеством возможных типов данных. Если рабочая задача не включает в себя весь диапазон возможностей, то она не будет точно отражать изменения производительности для других типов данных. Например, если интеллектуальное бизнес-приложение имеет трудности при импорте данных некоторого типа, то обнаружение этого факта требует наличия этого типа данных в тестовой задаче.
  • Не тратьте слишком много времени, пытаясь создать идеальную тестовую задачу. Не бывает идеальной тестовой задачи для всех случаев, целью должно быть создание такой задачи, по которой можно оценивать производительность, с хорошим покрытием кода приложения, и соответствующую приведенным выше соображениям. Назначьте себе срок на создание рабочей задачи и придерживайтесь выбранных временных рамок.


Третий этап: создание тестового окружения

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

Выбор оборудования и установка тестового компьютера

Как уже было сказано, идеальным вариантом является выделенная тестовая машина, поскольку в таком случае минимизируется вероятность возникновения неконтролируемых изменений, которые могут повлиять на результат. При выборе платформы лучше остановиться на современном варианте, поскольку старая модель под давлением новой может быстро выйти из употребления. Оптимизация производительности – очень важное дело, к нему надо относиться соответствующим образом, т.е. стоит подумать о покупке машины, максимально соответствующей целевым системам, которыми пользуются конечные потребители вашего продукта.

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

Средства и процессы автоматизации тестов

Циклическая природа тестового процесса свидетельствует о том, что в нем участвуют разнообразные повторяющиеся задачи, и в действительности есть положительная зависимость между количеством итераций и качеством конечного результата. Проще говоря, тестирование программы может стать затяжным процессом, что может привести к двум следствиям: он может надоесть и в него могут проникнуть ошибки. Автоматизация тестовых процедур там, где это имеет смысл, приводит к улучшению эффективности и точности результатов, а также помогает бороться со скукой.

При автоматизации можно применять различные средства: AutoIt, AutoMate или QuickMacros. Они в большом количестве присутствуют на рынке, некоторые из них распространяются бесплатно. При выборе подходящего средства нужно исходить из возможностей максимальной интеграции с другими процессами и инструментами, которые вы используете. Хотя эти средства обычно строятся с расчетом на такую интеграцию, но возможность написания собственных скриптов на Perl или Windows PowerShell может давать дополнительную гибкость.

Еще одним важным дополнением к процессу может стать Intel Concurrency Checker, который проверяет, работают ли потоки приложения согласованно. Его можно использовать для измерения производительности, запуская приложение до и после оптимизации кода и сравнивая результаты. Этот инструмент интегрируется в автоматизированный процесс с помощью командной строки или из скрипта, хотя можно запускать его и из графического интерфейса. Одним из достоинств Intel Concurrency Checker является то, что его можно использовать и без доступа к исходным кодам приложения, поэтому он применим и для тестирования уровня параллелизации закрытых программ конкурирующих организаций, которые также влияют на системные показатели.

Выработка необходимых настроек тестовой системы и изменений кода

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

Дополнительная информация по третьего этапа для вдумчивого оптимизатора производительности

Entrepreneur Network's Automation Software page содержит список утилит, которые можно использовать для автоматизированных повторяющихся задач, которые обычно встречаются при оптимизации.


Заключение

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

Поделитесь своими мыслями с сообществом

Расскажите нам о своих успехах в оптимизации, о том, что принесло плоды, а что нет, пообщайтесь со специалистами и экспертами Intel, разрешите свои вопросы (или помогите их разрешить другим):
Community Forum: Threading on Intel® Parallel Architectures

Материалы для дальнейшего изучения

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

Пожалуйста, обратитесь к странице Уведомление об оптимизации для более подробной информации относительно производительности и оптимизации в программных продуктах компании Intel.

Комментарии

Аватар пользователя Дмитрий

Как таковая параллельность, да и оптимизация ни при чем здесь, в равной степени это относится к обычным приложениям