Оптимизация параллельной программы
В предыдущих разделах рассматривались следующие вопросы построения кластера и создания программ для запуска на кластере:
- аппаратной основы кластера;
- системного обеспечения, необходимого для работы кластера;
- оценка эффективности построенного кластера;
- среды разработки параллельных программ.
Следующим шагом после разработки работающей параллельной программы является её оптимизация.
Многопоточный подход к разработке приложений появился в программировании уже достаточно давно и широко используется для повышения производительности. С появлением многоядерных процессоров интерес к многопоточному программированию значительно усилился. Многоядерные системы прошли путь от лабораторных образцов до настольных компьютеров, доступных рядовым пользователям. В 2005 году началась массовая продажа процессоров с двумя ядрами, в 2007 - четырехъядерных процессоров. В будущем ожидается сохранение тенденции увеличения числа ядер, и можно с уверенностью сказать, что с течением времени число систем, построенных на базе многоядерных процессоров, будет постоянно увеличиваться.
В подобной ситуации остро встает вопрос об эффективном использовании многоядерных архитектур. Многопоточное программирование представляет собой очень удобный подход, позволяющий создавать приложения, способные рационально использовать процессоры с несколькими ядрами, обеспечивая их оптимальную загрузку. Уже сегодня подавляющее большинство существующих приложений использует несколько потоков: браузеры, файловые менеджеры, словари, антивирусы и многие другие. Можно ожидать, что в дальнейшем все больше приложений будет изначально разрабатываться как многопоточные.
Необходимо, тем не менее, отметить, что разработка многопоточных приложений зачастую на порядок сложнее, чем последовательных. Новая парадигма приносит не только новые возможности, но и новые сложности. Создание эффективных многопоточных приложений - весьма трудоемкий процесс, а значит, имеется насущная необходимость в инструментальной поддержке всех стадий разработки подобных приложений, начиная с построения архитектуры и заканчивая настройкой параметров и финальной оптимизацией приложения.
В настоящее время существует достаточно много инструментов, ориентированных на поддержку многопоточного программирования. Компания Intel выделяется на общем фоне тем, что предлагает целое семейство подобных инструментов, представителем которого является Intel® Thread Profiler (ITP).
10.1. Семейство инструментов Intel для поддержки разработки многопоточных приложений
Цикл разработки программных приложений включает в себя следующие основные стадии: анализ требований, разработка архитектуры, реализация, тестирование, отладка и оптимизация. Зачастую при этом приходится проходить несколько раз по каждой из стадий. Эта деятельность разработчиков требует наличия специализированных инструментов, и в настоящее время компания Intel® предлагает целый ряд программных продуктов, предназначенных для поддержки разработки многопоточных приложений:
- Intel® C/C++ Compiler и Intel® Fortran Compiler - компиляторы;
- Intel® Performance Libraries - библиотеки математических функций (численные методы, обработка сигналов, генераторы случайных чисел);
- Intel® VTune Performance Analyzer - профилировщик;
- Intel® Thread Checker - отладчик многопоточных приложений;
- Intel® Thread Profiler - профилировщик многопоточных приложений;
- Intel® Threading Building Blocks - С++ библиотека времени выполнения, представляющая набор примитивов для разработки многопоточных приложений (параллельные алгоритмы, потокобезопасные структуры данных, примитивы синхронизации).
Данное семейство инструментов предназначено для поддержки всего цикла разработки многопоточных приложений. Их конечная цель - значительно ускорить процесс разработки, обеспечив разработчиков удобными и эффективными инструментами. Инструменты поддерживают различные методы создания многопоточных приложений: OpenMP, Pthreads, Win32 Threading API, автоматическое распараллеливание. Более подробную информацию можно найти на сайте http://www.intel.com/software/products.
На рис. 10.1 схематически представлен цикл разработки многопоточного приложения с указанием программных продуктов компании Intel, предназначенных для помощи на соответствующих стадиях.
Как видно из диаграммы, ITP в основном призван помочь разработчикам на финальных стадиях создания многопоточного приложения. Он предназначен для профилирования многопоточных приложений с целью их последующей оптимизации и финальной настройки. Однако следует заметить, что ITP может оказаться полезным еще на стадии разработки архитектуры. Разработчик имеет возможность сравнивать между собой различные архитектурные решения, создавая прототипы и сравнивая их производительность при помощи ITP и VTune.
10.2. Определение и цели профилирования
Центральная идея ускорения последовательных приложений достаточно проста. Необходимо выявить участки кода, в которых приложение проводит основную часть времени и оптимизировать их. Известен эвристический закон "20/80", утверждающий, что приложение проводит 80% времени работы в 20% кода. Таким образом, за счет оптимизации именно этих 20% кода можно добиться значительного повышения производительности. Как раз для поиска таких узких мест используются специальные средства, называемые профилировщиками.
Под понятием профилирование обычно понимается процесс анализа производительности приложения и учета потребляемых им ресурсов. Тем самым, профилировщик - это инструмент, при помощи которого осуществляется профилирование.
Профилировщики исследуют поведение программы в процессе ее выполнения. В частности, собирается такая информация, как частота вызовов функций, продолжительность их работы, число потоков, время ожидания - любая информация, способная помочь при оптимизации производительности. В числе приемов, используемых профилировщиками для сбора информации, инструментация кода, аппаратные прерывания, внедрение счетчиков производительности и многие другие. Выходной информацией профилировщика является трасса - список событий, произошедших в приложении (исполненные инструкции, вызовы функций, вызовы операционной системы). После получения трассы профилировщик обрабатывает собранную информацию и строит профиль приложения - статистическую сводку о работе приложения. Затем профиль представляется в графическом виде, удобном для анализа. Разработчик изучает его, определяет проблемные места и ищет способы оптимизации своего приложения.
Ситуация с многопоточными приложениями существенно другая, поскольку в силу вступают новые аспекты производительности, связанные с взаимодействием потоков, затратами на их создание и синхронизацию. Ускорение отдельных участков кода может не дать никакого прироста производительности, если, например, разработчик построил свое приложение таким образом, что основную часть времени потоки ожидают освобождения разделяемого ресурса. Также можно упомянуть такие распространенные в многопоточных приложениях проблемы как неравномерное распределение нагрузки и неэффективное использование примитивов синхронизации. Эти факторы могут привести к катастрофически низкой производительности приложения, вплоть до того, что многопоточная версия будет медленнее последовательной.
Таким образом, для анализа новых аспектов программной оптимизации, присущих именно многопоточным приложениям, необходимы специальные инструменты, ориентированные на обнаружение проблемных ситуаций и последующей помощи программистам в их разрешении. Одним из самых эффективных и популярных представителей инструментов такого класса является ITP.
10.3. Назначение Intel Thread Profiler
ITP предназначен для профилирования многопоточных приложений и помощи разработчику в процессе оптимизации программного кода. Следует напомнить, что ITP также может быть использован на стадии разработки архитектуры приложения. Разработчики могут создать несколько прототипов, соответствующих различным архитектурным решениям, и сравнить их производительность при помощи ITP. Также ITP может быть использован для анализа масштабируемости приложения. Например, если заранее известны характеристики компьютерной системы (число процессоров или ядер), на которой будет функционировать приложение, то ITP можно использовать для подбора оптимального числа потоков.
Итак, ITP может оказать разработчикам существенную помощь при решении проблем, связанных с производительностью многопоточного приложения. Перечислим основные варианты использования Intel® Thread Profiler:
- анализ эффективности распределения вычислительной нагрузки между потоками (подраздел 4.1, лабораторная работа 1);
- анализ эффективности обращения к разделяемым ресурсам (подраздел 4.2, лабораторная работа 2);
- определение наиболее медленных потоков и, как результат, нуждающихся в оптимизации (лабораторная работа 1);
- выбор оптимальной архитектуры многопоточного приложения (число потоков, алгоритм, примитивы синхронизации) (лабораторная работа 2);
- анализ эффективности работы с потоками и примитивами синхронизации (лабораторная работа 2);
- анализ масштабируемости приложения на вычислительных узлах с различным числом процессоров.
Таким образом, ITP является весьма удобным и эффективным инструментом для поиска причин низкой производительности многопоточного приложения и последующей помощи в их устранении.
10.4. Технические характеристики Intel Thread Profiler
10.4.1. Поддерживаемые методы создания многопоточных приложений
ITP позволяет профилировать многопоточные приложения, созданные на основе технологий OpenMP, Windows threads, POSIX threads.
Инструмент имеет два режима: "OpenMP" и "Threaded". Первый из них используется для анализа приложений, созданных с использованием OpenMP и скомпилированных компиляторами компании Intel. Этот режим предлагает возможности сбора и отображения следующей информации:
- затраты на синхронизацию, накладные расходы на поддержку работы с потоками;
- дисбаланс вычислительной нагрузки;
- сравнение результатов разных запусков.
Главной особенностью этого режима является возможность оценивания потенциальной масштабируемости, что очень удобно при создании параллельного прототипа приложения.
Второй режим является более общим - он обеспечивает анализ OpenMP приложений и многопоточных приложений, основанных на использовании Windows threads или POSIX threads. В этом режиме отображается следующая информация:
- аналогичные "OpenMP" режиму данные по потокам программы и уровню паралеллизма;
- критический путь программы;
- распределение временных затрат по критическому пути на:
- исполнение;
- синхронизацию;
- ожидание;
- блокировку.
- связь потоковых событий с исходным кодом.
Режим "Threaded" предоставляет более богатые возможности, поэтому мы сосредоточимся на рассмотрении именно этого режима.
10.4.2. Системные требования
10.4.2.1. Аппаратное обеспечение
Минимальные требования:
- Процессор Intel® Pentium 4;
- ОЗУ 512 МБ;
- Свободное дисковое пространство 300 МБ.
При практическом использовании ITP для достижения приемлемых показателей оперативности работы могут быть рекомендованы повышенные требования к минимально-необходимым аппаратным ресурсам:
- Процессор Intel® Pentium 4, поддерживающий технологию Hyper-Threading, или процессор Intel® Xeon;
- ОЗУ 2 ГБ.
Для изучения всех аспектов "реальных" параллельных вычислений желательно использование многоядерных процессоров компании Intel.
10.4.2.2. Программное обеспечение
Минимальные требования:
- Microsoft® Windows® XP Professional, или Microsoft® Windows® Server 2003.
- Microsoft® Visual C++® 6.0 или выше.
- Microsoft® Internet Explorer® 6.0 или выше.
- Adobe® Acrobat® Reader.
Для анализа OpenMP-приложений и инструментации на уровне исходных кодов требуется следующее программное обеспечение: