поддерживаю выше заданые вопросы
|
Введение в использование инструментов для параллельного программирования на примере пакета Intel Parallel Studio
Основные концепции и понятия профилирования
Понятие критического пути.
Первое понятие, которое нам понадобится, - критический путь (critical path). Оно является ключом к пониманию всего процесса профилирования, поэтому очень важно хорошо усвоить его. Прежде чем дать формальное определение этого понятия, попытаемся понять его суть на примере.
Представим себе следующее многопоточное приложение: имеется основной поток, который подготавливает данные и производит их первичную обработку, а также один дочерний поток, который завершает обработку и выводит результаты. Простейшая иллюстрация этого примера - физическое моделирование, в котором основной поток занят вычислениями (например, решением разностной схемы), а дочерний - подготовкой к визуализации и непосредственно визуализацией результатов вычислений. Часто подобные взаимодействия реализуются в виде конвейера, поскольку в то время как один из потоков работает с устройствами ввода-вывода, второй поток может нагружать процессор вычислениями.
В нашем случае, как только первый поток вычислил первую порцию данных для отображения, он может начинать вычисление следующей порции, а второй поток параллельно с этим начнет визуализацию. Важно при этом обеспечить син-хронизацию между потоками, чтобы не допустить уничтожения данных, до того как они были визуализированы.
Ниже (рис. 6.17) графически представлено взаимодействие потоков в случае, если бы требовалось выполнить только две итерации. Потокам в нашем приложении соответствуют горизонтальные линии, сплошные участки - активному состоянию потоков, а пунктирные - состоянию ожидания. Диагональные линии соответствуют сигналам, передаваемым между потоками, а проекции этих линий на ось времени - временам прохождения сигналов. Кружками обозначены все события, в результате которых изменяются состояния потоков (создание/завершение, блокировка/активизация).
Рассмотрим диаграмму подробнее. В начальный момент времени существовал только один поток, выполняющийся последовательно. Затем в момент времени t1 происходит создание дочернего потока, который начинает функционировать в момент времени t2, но сразу попадает в состояние ожидания, поскольку данные для визуализации еще не подготовлены. Затем в точке t3 завершаются вычисления, и дочерний поток начинает визуализацию подготовленных данных, которая про-должается с момента t4 до момента t7. Заметим, что второй поток может освободить массивы с результатами вычислений сразу после того, как переведет их в формат, необходимый для графического представления (момент времени t5). За счет этого и достигается распараллеливание в рассматриваемом приложении. Можно видеть, что потоки работают параллельно на промежутке времени между моментами t6 и t7. Далее осуществляется еще одна итерация, после чего в момент времени t12 второй поток завершает свое исполнение, а в момент времени t14 завершается весь процесс.
Рассмотренная диаграмма представляет собой граф. Вершинам, как уже говорилось, соответствуют события, изменяющие состояние потоков, а ребрам - действия, выполняемые потоками (мы не учитываем пунктирные линии). При этом ребрам можно сопоставить вес, равный времени, затрачиваемому на выполнение действия. Путем приложения называется любой путь в указанном графе, соединяющий вершины, соответствующие началу и завершению приложения. Критическим путем приложения называется путь, имеющий максимальную сумму весов входящих в него ребер. Приложения со многими потоками могут иметь большое число путей, однако в нашем случае приложение имеет всего два пути, каждый из которых можно назвать критическим, так как суммы их весов совпадают. Важность понятия критического пути определяется тем, что сумма весов ребер в критическом пути равна времени выполнения приложения. Из этого факта вытекает следующий принцип: необходимо оптимизировать прежде всего те участки приложений, которые вошли в критический путь, поскольку именно они определяют производительность.
Таким образом, профилирование и оптимизация приложения неразрывно связаны с процессом анализа критического пути. Критический путь - это первое, на что нужно обращать внимание, поскольку не входящие в него участки приложения вносят меньший вклад в суммарное время работы. Далее мы увидим, что ITP позволяет строить критический путь приложения и предоставляет различные средства для его анализа.
Состояния потоков
При анализе критического пути пользуются таким понятием, как состояние потока (thread state). А именно, поток может находиться в трех состояниях:
- Активное состояние (active) - поток исполняется в настоящее время;
- Состояние активного ожидания (spin) - постоянно повторяемая проверка состояния блокировки (например, при использовании pthread_spin_ lock());
- Состояние ожидания (wait) - ожидание завершения какой-либо блокирующей операции (например, операции ввода-вывода).
Понятие категорий времени
Рассмотрим теперь характеристики эффективности использования аппаратных ресурсов активными потоками приложения. Для этого в ITP используются два параметра:уровень параллелизма (concurrency) и поведение (behavior).
Уровни параллелизма используются для обозначения того, насколько полно потоки нагружают процессоры вычислительного узла. Так, одновременная работа двух потоков на двухъядерном процессоре означает эффективное использование его ресурсов (full utilization), на одноядерном - сверхиспользование (over utilization), а на четырехъядерном - недостаточно эффективное использование (under utilization).
Существует несколько типов поведения потока в активном состоянии:
- Сдерживание (impact) - ситуация, когда поток сдерживает выполнение другого потока (например, поток занял мьютекс, освобождения которого ожидают другие потоки);
- Блокировка (blocking) - приостановка потока в результате вызова блокирующих функций (например, операций ввода/вывода);
- Критический путь (critical path) - ситуация, когда поток выполняет участок кода, входящий в критический путь, при отсутствии других ожидающих потоков.
Уровень параллелизма и поведение независимы друг от друга, и в совокупности они называются категориями времени (time categories) и характеризуют эффективность работы активных потоков. Собственно весь анализ произво-дительности состоит в том, чтобы оценить каждый участок критического пути по этим двум параметрам и определить наиболее проблемные участки приложения.
В ITP используется несколько видов представления критического пути, каждое из которых мы впоследствии подробно изучим. Для удобства анализа каждый участок критического пути окрашивается в определенный цвет в зависимости от уровня параллелизма и поведения потока на этом участке. На рис. 6.18 представлена сводная таблица используемых цветов; n обозначает число активных потоков приложения, а p - число процессоров (ядер).
Рассмотрим приведенную таблицу подробнее, чтобы знать впоследствии, на какие цвета нужно обращать внимание прежде всего. Сначала исследуем связь числа потоков и числа ядер. Как видно из таблицы, для обозначения этого соот-ношения используется четыре цвета: оранжевый, красный, зеленый и синий. Зеленый цвет - признак оптимального соотношения, когда число ядер и потоков совпадает. Синий цвет используется для обозначения ситуаций, когда одновременно работает больше потоков, чем доступно ядер. Как результат, потоки могут мешать работе друг друга. Присутствие красного и оранжевого цветов в окраске критического пути чаще всего свидетельствует о необходимости перестройки приложения. Эти цвета означают, что используются не все ядра процессора и можно получить дополнительное ускорение за счет более эффективного распараллеливания.
Рассмотрим теперь второй параметр - тип поведения потоков. Для обозначения типа поведения потока цветом используется изменение яркости. При этом используется простое правило: чем ярче цвет участка, тем большего внимания от разработчика он требует. Самый яркий цвет используется для указания impact-состояния потока, поскольку прежде всего необходимо сокращать время ожидания потоков. Далее по важности следует blocking-состояние, которое тоже требует пристального контроля, так как нужно минимизировать время ожидания потоков. Последним идет состояние critical path.
Имеется особая категория времени, обозначаемая желтым цветом и указывающая на непроизводительные издержки (overhead) в многопоточном приложении. Под непроизводительными издержками понимаются накладные расходы на создание потоков, управление и синхронизацию между потоками. Другими словами, эта величина показывает количество процессорного времени, израсходованного на поддержку работы потоков. Чаще всего большая доля желтого цвета в критическом пути свидетельствует о чрезмерно частом вызове функций синхронизации и необходимости перепроектирования приложения.
Теперь, зная о категориях времени, мы можем сказать, какие цвета будут содержаться на критическом пути нашего примера из раздела 3.3.1.
увеличить изображение
Рис. 6.19. Пример раскраски критического пути многопоточного приложения в соответствии с категориями времени
Итак, подведем итоги: профилирование многопоточного приложения основано на построении критического пути и его анализе с точки зрения эффективности использования процессора. Для этого выделяют категории времени, часть которых считаются проблемными и свидетельствуют о неправильной организации многопоточного приложения. Деятельность разработчика, таким образом, состоит в нахождении проблемных участков критического пути, выявлении причин (соотнесение с исходным кодом) и в последующем их разрешении.