79338
Отладка эффективности OpenMP-программ
Дипломная
Информатика, кибернетика и программирование
В современных условиях необходимость обработки все больших и больших объемов информации постоянно ставит перед программистами задачи повышения производительности разрабатываемых ими систем. Поскольку сейчас широкое распространение получили многоядерные процессоры, практически в любой системе используются SMP-элементы.
Русский
2015-02-11
1.07 MB
4 чел.
Московский государственный университет им. М. В. Ломоносова
Факультет вычислительной математики и кибернетики
Кафедра системного программирования
Дипломная работа
Отладка эффективности OpenMP-программ
Выполнил
Гильмендинов Михаил Александрович
группа 528
Научный руководитель
профессор, д.ф.-м. н.
Крюков Виктор Алексеевич
Москва, 2010 г.
Содержание
[1] Аннотация. [2] Введение [3] 1. Постановка задачи [4] 2. Обзор существующих решений [4.1] 2.1. Intel Thread Profiler [4.2] 2.2. PGPROF [4.3] 2.3. ompP [4.4] 2.4. KOJAK [4.5] 2.5. APART [4.6] 2.6. Анализатор DVM. [4.7] 3.1. Используемые термины [4.8] 3.2. Накопление трассы [4.9] 3.4. Сбор статистики [4.10] 3.5. Соглашение об именовании файлов. [4.11] 3.6. Анализ [4.12] 3.7. Анализ MPI/OpenMP и DVM/OpenMP программ [4.13] 3.8. Получение читаемой трассы [4.14] 3.9. Указания для правильной расстановки интервалов. [5] 4. Особенности реализации [5.1] 4.1. Трассировщик [5.2] 4.2. Анализатор [6] 5. Замедление проинструментированных программ и расчет требуемых ресурсов [7] 6. Дальнейшее развитие [8] Заключение [9] Литература [10] Приложение А. Описание используемых функций инструментации и контекстных строк [11] Приложение Б. Формат промежуточной трассы [12] Приложение В. Формат протокола анализатора. [13] Приложение Г. Формат читаемой трассы [14] Приложение Д. Ключи анализатора [15] Приложение Е. Пример работы трассировщика и анализатора |
Целью данной дипломной работы является создание набора инструментов для анализа и отладки эффективности программ в гибридной модели DVM/OpenMP и MPI/OpenMP. Выдаваемые характеристики эффективности должны соответствовать характеристикам анализатора эффективности системы DVM.
Практическим результатом дипломной работы является разработка трассировщика и анализатора эффективности OpenMP-программ.
.
В современных условиях необходимость обработки все больших и больших объемов информации постоянно ставит перед программистами задачи повышения производительности разрабатываемых ими систем. Поскольку сейчас широкое распространение получили многоядерные процессоры, практически в любой системе используются SMP-элементы [14]. Стандартом программирования для компьютеров с SMP архитектурой стал OpenMP [4]. Применение MPI в рамках данной архитектуры не очень эффективно ввиду использования сообщений как единственного средства взаимодействия между процессами
За счет идеи "инкрементального распараллеливания" OpenMP идеально подходит для разработчиков, желающих быстро распараллелить свои вычислительные программы с большими параллельными циклами. Разработчик не создает новую параллельную программу, а просто добавляет в текст последовательной программы OpenMP-директивы.
Стоит отметить некоторые особенности OpenMP-программ:
Пользователь разрабатывает параллельную программу для ускорения решения существующих задач, для возможности решения тех задач, которые из-за ограничений по времени или памяти не может решать сегодня.
Его может интересовать возможность решения вообще, время решения. Если думать о масштабировании (решении больших задач на большем числе процессоров), то его интересует коэффициент эффективности. Когда эти характеристики его не устраивают, он вынужден анализировать и отлаживать эффективность.
Для анализа эффективности программ обычно используется трассировка программ. Для целей трассировки в исследуемую программу встраиваются "профилировочные" вызовы, которые фиксируют наступление определенных событий или продолжительность интервалов, и фиксируют эту информацию в журнале трассировки, передают ее онлайн-анализатору или просто модифицируют собираемую статистику.
Существуют общие проблемы всех средств трассировки:
Центральная идея ускорения последовательных приложений достаточно проста. Необходимо выявить участки кода, в которых приложение проводит основную часть времени и оптимизировать их. Известен эвристический закон "10/90", утверждающий, что приложение проводит 90% времени работы в 10% кода. Таким образом, за счет оптимизации именно этих 10% кода можно добиться значительного повышения производительности. Как раз для поиска таких узких мест используются специальные средства, называемые профилировщиками.
Под понятием профилирование обычно понимается процесс анализа производительности приложения и учета потребляемых им ресурсов. Тем самым, профилировщик - это инструмент, при помощи которого осуществляется профилирование.
Профилировщики исследуют поведение программы в процессе ее выполнения. В частности, собирается такая информация, как частота вызовов функций, продолжительность их работы, число потоков, время ожидания - любая информация, способная помочь при оптимизации производительности. В числе приемов, используемых профилировщиками для сбора информации - инструментация кода, аппаратные прерывания, внедрение счетчиков производительности и многие другие. Выходной информацией профилировщика является трасса - список событий, произошедших в приложении. После получения трассы профилировщик обрабатывает собранную информацию и строит профиль (протокол) приложения - статистическую сводку о работе приложения.
Задача заключается в разработке инструментов для анализа и отладки эффективности OpenMP-программ и программ использующих гибридные модели MPI/OpenMP и DVM/OpenMP. Использовать доступные инструменты (ITP и др.) на узлах кластера проблематично. Кроме этого планируется объединение существующих в DVM-системе средств отладки эффективности DVM и MPI со средствами отладки эффективности OpenMP. Поэтому необходимо разработать средства для отладки OpenMP-программ совместимые на уровне выдаваемых характеристик с DVM-системой.
В имеющихся в DVM-системе средствах отладки эффективности DVM и MPI были
использованы два метода сбора характеристик - накопление статистики (для DVMпрограмм) и накопление трассы (для MPI-программ). При первом подходе не требуется дополнительного дискового пространства, но при этом нет такой детальности, как при накоплении полной трассы.
Для реализации решено использовать сокращенную трассу со статистикой, в которой отражаются события, но для повторяющихся событий статистика вычисляется во время выполнения программы, что существенно сокращает размер трассы.
Существует 2 основных подхода к анализу программ sample-based profiling (sampling) и instrumentation-based profiling.
Самплинг код программы не меняется. Производится сбор образцов (samples) это может быть стек вызовов, аппаратные счетчики производительности, системные вызовы, промахи кеша и др. Sampling не позволяет анализировать конкретные события в программе. Существует много инструментов для семплинга, например, Visual Studio Team Suite Profilers, CLRProfiler, PerfMon, ETWB, OProfile [11], XProf, но в данном обзоре средства для sample-based profiling не рассматриваются.
Второй подход подразумевает вставку в программу (исходный код или непосредственно в скомпилированный файл) особых вызовов функций, соответствующих каким-либо событиям программы (вызовам функций и т.п.). С помощью instrumentation-based profiling можно производить измерения интересующих событий в программе. К недостаткам можно отнести влияние встроенных в программу вызовов на производительность.
В данном обзоре рассмотрены наиболее популярные инструменты для анализа и отладки эффективности OpenMP-программ, а также гибридных MPI/OpenMP программ, основанных на instrumentation-based profiling. Все они ориентированы на инструментацию программы и работу с полученной трассой. Среди них есть как проприетарные (например, Intel Thread Profiler или PGPROF) так и open source проекты (например, ompP). Также рассмотрен анализатор системы DVM.
ITP [6] разработан компанией intel и предназначен для профилирования многопоточных приложений и помощи разработчику в процессе оптимизации программного кода. Инструмент имеет два режима: "OpenMP" и "Threaded". Первый из них используется для анализа приложений, созданных с использованием OpenMP и скомпилированных компиляторами компании Intel. Этот режим предлагает возможности сбора и отображения следующей информации:
Второй режим является более общим - он обеспечивает анализ OpenMP приложений и многопоточных приложений, основанных на использовании Windows threads или POSIX threads. В этом режиме отображается следующая информация:
Для анализа эффективности с помощью ITP используется критический путь программы.
Рис.1. Критическому пути соответствет путь с ребрами, обозначенными сплошными линиями.
Работа программы представляется в виде графа. Вершинам соответствуют события, изменяющие состояние потоков, а ребрам - действия, выполняемые потоками. При этом ребрам можно сопоставить вес, равный времени, затрачиваемому на выполнение действия. Путем приложения называется любой путь в указанном графе, соединяющий вершины, соответствующие началу и завершению приложения. Критическим путем приложения называется путь, имеющий максимальную сумму весов входящих в него ребер. Важность понятия критического пути определяется тем, что сумма весов ребер в критическом пути равна времени выполнения приложения. Из этого факта следует следующий принцип: необходимо оптимизировать прежде всего те участки приложений, которые вошли в критический путь, поскольку именно они определяют производительность.
В ITP две основные характеристики эффективности:
Уровни параллелизма используются для обозначения того, насколько полно потоки нагружают процессоры вычислительного узла. Так, одновременная работа двух потоков на двухъядерном процессоре означает эффективное использование его ресурсов (full utilization), на одноядерном - сверхиспользование (over utilization), а на четырехъядерном - недостаточно эффективное использование (under utilization).
Существует несколько типов поведения потока в активном состоянии:
Уровень параллелизма и поведение независимы друг от друга, и в совокупности они называются категориями времени (time categories) и характеризуют эффективность работы активных потоков. Собственно весь анализ производительности состоит в том, чтобы оценить каждый участок критического пути по этим двум параметрам и определить наиболее проблемные участки приложения.
PGPROF [10] - разработка компании The Portland Group. Этот инструмент является статистическим анализатором для параллельных MPI и OpenMP программ. PGPROF сопоставляет время выполнения с исходным кодом и инструкциями программы, что позволяет видеть, где и как тратится время. PGPROF позволяет посмотреть, как влияют конкретные участки кода на ускорение или замедление программы.
Рис. 2. визуализация работы инструмента PGPROF
Столбец Scale показывает, например, что функция f_nonbon, выполняется с ускорением, в то время как некоторые другие функции замедляют работу.
PGPROF позволяет анализировать до 64 OpenMP-нитей и собирать информацию о программе различными способами, такими как инструментирование или самплинг, однако требует использования специального компилятора. Результаты представляются в виде временных диаграмм (time view).
Профилировщик и визуализатор ompP [7], разработанный Technische Universitat Munchen, вычисляет средние характеристики, строит граф вызовов и анализирует накладные расходы. Использует OPARI [9] в качестве инструментатора.
Выдает такие характеристики как:
Связывает openmp-регионы с исходным кодом.
Накладные расходы оцениваются абсолютным временем и процентным отношением ко времени работы программы.
Рис.3. схема работы инструмента ompP
T=time, C=count
Рис.4. ompP: времена и счетчики для различных OpenMP-конструкций
ompP выделяет 4 категории накладных расходов:
KOJAK [5] представляет собой набор средств для автоматизированного анализа эффективности параллельных OpenMP-программ и гибридной модели MPI/OpenMP. Разрабатывается совместно University of Tennessee и Julich Forshungszentrum.
Рис. 5. схема работы инструмента KOJAK.
KOJAK ориентирован на модель MPI/OpenMP и представляет ограниченный набор характеристик:
Является разработкой IST Working Group. APART [8] это набор инструментов для автоматического анализа эффективности программ на MPI, OpenMP и HPF. Характеристики, выдаваемые при анализе OpenMP-программ, представляют собой смесь интегральных характеристик и причин плохой производительности. Например, к характеристикам относятся:
Условно характеристики делятся на 4 вида:
Этот инструмент не предназначен для анализа и отладки эффективности OpenMP программ, но включен в обзор, т.к. во-первых, помимо анализа OpenMP и MPI/OpenMP программ в этой работе рассматривается анализ DVM/OpenMP программ. Во-вторых, характеристики, выдаваемые анализатором, описываемым в этой работе, соответствуют характеристикам, выдаваемым анализатором эффективности DVM [3]. Кроме того, анализатор DVM считает характеристики «на лету» - т.е. не создает трассу, а выдает только «протокол» содержащий результат анализа. Инструментация DVM-программ производится автоматически при их компиляции. При этом с помощью специальных комментариев в исходной программе можно задать пользовательские интервалы и собирать характеристики по ним. Нужная степень подробности протокола задается параметрами запуска анализатора. Пример протокола:
Рис.6. пример протокола анализатора эффективности системы DVM.
Подробно система DVM описана в [15]
3. Сбор данных и анализ эффективности.
Инструментатор [1] программа, которая вставляет в программу вызовы специальных функций. В дальнейшем эти функции будем называть функциями инструментации. Кроме вставки вызовов функций, инструментатор может менять некоторые директивы OpenMP. Подробнее об этом в главе 3.3. Список используемых трассировщиком вызовов функций анализатора в приложении А.
Событие запись в трассе, отражающая выполнение отмеченного инструментатором фрагмента кода или директивы OpenMP. Директивы могут быть одиночными (например, барьер) или относится к фрагменту кода (например, параллельная область). Запись в трассе содержит накопленную за время работы статистику, относящуюся к выполнению фрагмента кода или директивы. Подробнее о сборе статистики см. главу 3.4.
Интервал выполнение фрагмента кода, обрамленного функциями инструментации, которому в трассе соответствуют пары записей (вход в интервал и выход из него), между которыми располагаются события, произошедшие внутри интервала. Интервалы нужны для того, чтобы получать характеристики не для всей программы, а для обозначенного пользователем участка программы. Интервалы имеют имена, которые задает пользователь. Интервалы могут быть вложенными и не могут пересекаться другим способом или один интервал включает в себя другой, или они не имеют общей области.
Трасса файл с событиями. Для каждой нити создается своя трасса и в ней отражены только те события, которые произошли в соответствующей нити. Трассы бывают двух видов промежуточная трасса, которая получается в результате работы проинструментированной программы и используется анализатором, и читаемая трасса, которая строится на основе промежуточной трассы и содержит подробное описание событий. Формат промежуточной трассы описан в приложении Б, формат читаемой трассы в приложении Г.
Трассировщик объектный файл, содержащий код функций инструментации и другие средства для создания промежуточной трассы и сбора статистики. Для накопления трассы трассировщик необходимо прилинковать к проинструментированной программе.
Контекстные строки генерируемые инструментатором строки, содержащие информацию о событии. Содержат информацию о расположении события или интервала в исходном коде, параметрах и именах функций и интервалов и клаузах openmp директив. Имеют формат:
Число*атр1=значение1*атр2=значение2* … **. Оканчиваются всегда на **. Число перед первой звездочкой это число символов в строке исключая само это число. Набор атрибутов и значений зависит от типа события. Контекстные строки регистрируются в начале выполнения программы и используются для анализа и составления читаемой трассы. При регистрации строки записываются во внешний файл. Подробнее контекстные строки описаны в [1] и приложении Б.
Точки SRC особо выделенные события, которые могут быть источником плохой производительности. К ним относятся вся синхронизация нитей барьеры (явные и неявные), замки, критические секции, директивы ordered, flush. Формат записи точек SRC в протоколе в приложении В.
Анализатор программа, работающая с промежуточными трассами и файлом, содержащим контекстные строки. В результате работы анализатора генерируется протокол, содержащий характеристики эффективности и список точек SRC. Также используется для генерации читаемой трассы. Формат протокола описан в приложении В.
Как уже было сказано выше, сначала программа инструментируется и запускается на выполнение. В результате получаются файлы с промежуточной трассой и файл с контекстными строками. При этом трасса не просто содержит события и время их возникновения, как в случае использования большинства рассмотренных в обзоре инструментов, но содержит уже посчитанную во время работы программы статистику. Если одно и то же событие повторилось больше одного раза, то для него считается статистика «на лету» и в трассе для него будет создана одна запись с указанием числа повторений и другой информации.
Получается «компромисс» между полной трассой и только выводом статистики как в системе DVM. Такой способ создания трассы позволяет существенно снизить размер трассы и сделать его практически независимым от числа итераций проинструментированных циклов. При этом часть времени программа вынуждена тратить на вычисление статистики. Информация по замедлению программ находится в главе 5. там же некоторые оценки по замедлению определенных задач при запуске с инструментацией. Пример промежуточной трассы см. в приложении Б.
3.3. Инструментация исходного кода
Инструментировать программу нужно с ключом dperf.
convert dperf <имя файла>
В этом режиме в программу вставляются только используемые при анализе эффективности вызовы, а также модифицируются некоторые директивы. Исходный код изменяется для конструкций разделения работ, не содержащих клаузу nowait. Без клаузы nowait в конце конструкций разделения работы происходит неявная барьерная синхронизация нитей. Для того чтобы оценить потери на неявном барьере, к конструкции разделения работы добавляется клауза nowait и ставится явный барьер:
call DBG_Before_OMP_Loop()
!$OMP DO
call DBG_OMP_Loop_Event()
...
!$OMP END DO NOWAIT
call DBG_BeforeBarrier()
!$OMP BARRIER
call DBG_AfterBarrier()
call DBG_AfterOMPLoop()
Схема.1 схема инструметирования параллельного цикла с клаузой nowait
При инструментации отмечаются следующие события:
Звездочками отмечены конструкции разделения работы. Все такие конструкции кроме master имеют клаузу nowait и инструментируются так как показано выше на схеме.1 если не указана клауза nowait. Если клауза указана, то барьер не ставится. Директива master не блокирует остальные нити и видна только в главной нити. Она инструментируется только изнутри. Директива atomic преобразуется инструментатором в критическую секцию.
Кроме этого, инструментируются вызовы функций если исходный код функции недоступен, то инструментатор вставляет вызовы перед и после вызова функции, иначе функция инструментируется также изнутри, подобно конструкции master. При этом вызовы, обрамляющие вызов проинструментированной функции снаружи считаются отдельно от вызовов инструментирующих тело функции и являются разными событиями.
Поскольку инструментатор не выделяет отдельно функции OpenMP для работы с замками, то если в программе есть замки их нужно явно указать вручную. Инструментатор передает имя функции omp_set_lock/omp_unset_lock и считает их разными событиями. Для анализа важно знать, сколько длилось ожидание перед захватом замка. Поэтому инструментировать нужно аналогично критической секции, только считать omp_set_lock и omp_unset_lock началом и концом одного события. Для этого нужно изменить контекстные строки, соответствующие вызовам set_lock/unset_lock. Вместо имени функции omp_set_lock необходимо указать @set_lock_<имя замка> (символ @ выбран поскольку не может встречаться в имени функции). Аналогично для omp_unset_lock имя функции задается как @unset_lock_<имя замка>. Имя замка может состоять из любых печатных символов. Имя замка для вызовов set_lock/unset_lock должно быть одинаковым для каждой пары вызовов.
Атрибут name1 для контекстной строки, описывающий замок (на примере omp_set_lock) должен иметь вид:
Name1=@set_lock_MyLock1.
Для вложенных замков аналогично, с заменой @set_lock на @set_nested @unset_lock на @unset_nested. Можно использовать @set_lock и @unset_lock для вложенных замков анализатор не выделяет отдельно вложенные замки и обрабатывает их так же.
Интервалы необходимо задавать вручную с помощью вызовов, соответствующих функциям (список используемых функций инструментатора с описаниями в приложении А), где в качестве имени функции нужно указать имя интервала.
Используется следующий формат контекстной строки:
Число*type=user_interval*file=названиефайла*line1=л1*line2=л2*name1=имя_интервала**
Л1 и Л2 строки в исходном файле в которых находится начало и конец интервала. Число в начале контекстной строки можно задать произвольное, но оно должно стоять при разборе контекстной строки само число не используется, но предполагается, что корректная контекстная строка содержит число в начале.
Во время работы проинструментированной программы собираются статистические данные о событиях и интервалах.
Для каждого интервала в трассу выдаются следующая информация:
Для каждого события в трассу выдается следующая информация:
Если событие или интервал вложены в другой интервал, то все перечисленные характеристики считаются отдельно для этого интервала. Это важно для вызовов проинструментированных функций собирается статистика для таких вызовов только в рамках интервала, а не по всей программе, что позволяет оценить в каком месте программы сколько времени ушло на вызов одной и той же функции (при выделении интересующего участка интервалом).
Файл с контекстными строками должен называться cstrings.csf либо можно явно указать анализатору какой файл использовать. Подробное описание ключей инструментатора содержится в приложении Д. файлы с трассой должны называться так trace.thrnum.mtr, где вместо thrnum стоит номер нити. Проинструментированная программа создает файлы именно в этом формате. В простейшем случае анализатор запускается без параметров, возможен запуск с указанием общей части имени для файлов с трассой (по умолчанию создаются файлы с первой частью имени trace).
Анализатор восстанавливает структуру вызовов по промежуточной трассе и файлу с контекстными строками. Это нужно для того, чтобы корректно сопоставить друг с другом события и интервалы из разных нитей. При анализе, если не указано явно, структура программы соответствует трассе главной нити, а события, не вошедшие в трассу главной нити, но вошедшие в трассы других нитей (это возможно, например, при использовании ветвлений, параллельных секций и т.д.) учитываются при подсчете характеристик, но не входят в читаемую трассу. После построения структуры вызовов, анализатор вычисляет характеристики эффективности. Эти характеристики основаны на характеристиках эффективности, выдаваемых анализатором системы DVM [3]. Ниже приведена таблица, показывающая характеристики, не соответствующие характеристикам выдаваемым анализатором системы DVM. Помимо этих характеристик выдаются и аналогичные используемым анализатором DVM-системы: execution time, total time, idle time, processors, efficiency
Название характеристики |
Анализатор OpenMP |
Productive Time |
Total Time - Idle Time сумма Lost Time по всем процессорам. |
Lost Time |
Простои в одной нити. Берется максимальное значение простоев среди всех нитей. Включает в себя Insufficient Parallelism, Desync Time, ожидание на барьерах замках и перед входом в критическую секцию, а также ожидание на ordered. |
Insufficient Parallelism |
Дулирование вычислений. Считается, что только одна нить выполняет полезную работу. Определяется как время внутри параллельной области вне конструкций разделения работы без учета барьеров, критических секций, замков и ordered. |
Desync Time |
время ожидания в конце конструкции разделения работы. Сумма по всем конструкциям. Также включает в себя ожидание на Flush. |
Таблица 1. характеристики отличающиеся от выдаваемых анализатором DVM
Можно схематично изобразить процесс инструментации, накопления трассы и анализа так:
Рис. 7. полная схема работы
При анализе учитываются следующие особенности:
В результате работы анализатора создается протокол, содержащий характеристики эффективности и точки SRC.
В гибридных программах обычно с помощью MPI и/или DVM задача разбивается на подзадачи, каждая из которых решается на одном SMP-узле. Эти подзадачи распараллеливаются с помощью OpenMP. Таким образом, для таких программ анализ для каждого узла производится отдельно. Можно запустить анализ только для того узла, на котором подзадача выполнялась дольше чем на других узлах или использовать другие критерии отбора.
На основе промежуточной трассы и файла с контекстными строками, анализатор может создавать читаемую трассу. Это можно сделать несколькими способами:
Подробнее о ключах анализатора в приложении Д.
На анализ и отладку эффективности большое влияние оказывает правильная расстановка интервалов. С их помощью можно точно локализовать кусок кода, который необходимо исследовать, поскольку анализатор может выдавать характеристики по конкретному набору интервалов. Кроме этого, существует такая проблема, как вызов функции или процедуры доступной для инструментации. Инструментатор отметит вызов функции и проинструментирует само тело функции. Функцию можно вызывать из разных мест в программе и если не ограничить интервалами нужные области с вызовами этой функции, то при накоплении трассы все вызовы будут посчитаны вместе, и в результате нельзя будет сказать в каком месте программы как вела себя функция. Также это важно в тех случаях, когда функции и процедуры вызываются в начале программы специально для того чтобы ускорить последующие вызовы так, например, поступили разработчики тестов NAS [2] перед работой самого теста все переменные инициализируются случайными значениями и вызываются все функции и процедуры.
Также следует размещать интервалы так, чтобы они повторялись как можно реже, т.е. стараться не размещать их внутри циклов с большим числом итераций это может усилить замедление программы, а для участков, где выполняется очень маленький объем работы может возникнуть замедление сравнимое с временем самой полезной работы, что делает результат анализа неточным.
Созданы два модуля системы: трассировщик и анализатор (включает в себя преобразователь промежуточной трассы в читаемую трассу).
Трассировщик написан на языке Си++ и предназначен для работы в 32 и 64 разрядных операционных системах Linux и Windows. Большая часть кода платформонезависима. При этом используются системные вызовы ОС:
Внутри модуля используются директивы и функции OpenMP:
Число нитей, для которых накапливается трасса, задается в начале выполнения программы, поэтому нельзя делать вызовы omp_set_num_threads с числом нитей большим, чем возвращает omp_get_proc_num.
При написании трассировщика использовались структуры данных из STL. Также использовались потоки ввода/вывода Си++. Все функции инструментатора объявлены как extern “C” для того, чтобы их можно было вызывать из программ на фортране и Си. При линковке трассировщика с проинструментированной программой необходимо так же прилинковывать стандартную библиотеку Си++. Под Linux это делается с помощью ключа lstdc++.
Исходный код трассировщика содержится в 3 файлах: deps.h, mmod.h, и mmod.cpp. Общий размер исходных файлов трассировщика более 900 строк кода. Для компиляции и запуска проинструментированной программы на фортране с использованием компилятора от intel в Linux можно сделать так:
icpc openmp c mmod.cpp
ifort openmp lstdc++ -o <имя выходного файла> mmod.o <имя программы>.f
./<имя выходного файла>
Версия компилятора Си++ (icpc в данном случае) и компилятора фортрана (ifort в данном случае) должны совпадать иначе могут быть проблемы с линковкой.
Инструментатор позволяет инструментировать только программы написанные на языке ФОРТРАН. Трассировщик может работать и с программами на языках Си и Си++, но инструментировать такие программы необходимо полностью вручную.
Трассировщик не поддерживает динамическое порождение нитей и вложенный параллелизм.
Анализатор написан на языке C#. Такой выбор был сделан из-за того, что сейчас широкое распространение получила среда выполнения .Net кода mono [12]. При использовании определенных сборок (assemblies) код может без перекомпиляции работать и в Windows, с установленным .Net framework v2 и на любой системе, на которой установлен mono. Сейчас большинство дистрибутивов Linux содержат в себе mono по умолчанию. Так, например, mono установлен на ВК СКИФ-МГУ [13]. Для запуска анализатора с использованием mono нужно выполнить команду:
mono manalizer <options>
Для запуска в Windows используется обычный синтаксис для запуска исполняемых файлов:
manalizer <options>
Анализатор также является и конвертером трасс. Для того чтобы перевести трассу из промежуточного формата в читаемый формат нужно запускать анализатор со специальными ключами. Описание способов преобразования трассы в разделе 3.8. Описание ключей анализатора в приложении Д. Размер исходного кода анализатора составляет более 1500 строк кода.
Несмотря на то, что во время работы проинструментированной программы происходит подсчет статистики, замедление получается совсем небольшим. Ниже приведен пример для теста NAS EP для классов A, B и C на 8 нитей на ВК СКИФ-МГУ [13].
Класс теста |
Время без трассировки, сек |
Время с трассировкой, сек |
Замедление, % |
A |
1,41 |
1,60 |
13% |
B |
5,58 |
6,41 |
14% |
C |
22,21 |
24,66 |
11% |
Таблица 2. замедление на тесте NAS EP.
В таблице указано среднее время за 10 запусков. Размер промежуточной трассы для одной нити составил около 2 килобайт. Размер трассы практически не зависит от класса теста.
На различных тестах удавалось получить разные значения замедления. Они уложились в диапазон от 1 до 30%. Самое большое замедление (около 30%) было получено для программы, в которой были вложенные циклы, внутри которых были вложенные интервалы и встречались барьеры и директивы ordered, причем практически никакой работы на каждой итерации цикла не выполнялось. Таким образом, можно считать, что в реальных программах замедление не будет превышать 20%.
Расход оперативной и дисковой памяти зависит от структуры программы. Рассмотрим пример: 10000 циклов по 1000000 итераций с 4 проинструментированными вызовами внутри каждого цикла. Одно событие требует sizeof(long)*11 байт. На 64 битных системах long обычно имеет размер 8, поэтому на одно событие требуется 88 байт. Любой интервал занимает меньше места и встречается значительно реже, поэтому будем считать только события. Для данного примера расход ОП под данные составит 4*4*88*10000 байтов, что составит примерно 13,5 Mb на нить. С учетом используемых структур данных эта цифра составит около 14 мегабайтов на нить. Для задачи такого размера это вполне приемлемое потребление памяти.
Промежуточная трасса для этой же задачи на одну нить составит около 17 мегабайтов из расчета 109 байтов на событие(10 байтов на разделители и 11 параметров по 9 значащих цифр). Формат промежуточной трассы описан в приложении Б.
В дальнейшем необходимо добавить поддержку динамического создания нитей. Текущая реализация некорректно работает с программами порождающими дополнительные нити после инициализации трассировщика число нитей жестко задается при инициализации и при вызове из нити, которой не было на момент вызова dbg_init поведение трассировщика неопределенно.
Кроме этого сейчас многие компиляторы поддерживают вложенный параллелизм в программах на OpenMP, поэтому нужно добавить эту функциональность в трассировщик.
Дипломная работа посвящена созданию средств для анализа и отладки эффективности OpenMP-программ и программ работающих в гибридной модели MPI/OpenMP и DVM/OpenMP.
Актуальность темы обусловлена тем, что сейчас ВК, суперкомпьютеры и даже домашние компьютеры оборудованы многоядерными процессорами. Стандартом программирования для таких систем является OpenMP. Без наличия средств анализа эффективности невозможно написание эффективных программ.
Были разработаны инструменты для анализа и отладки эффективности OpenMP-программ, которые можно использовать и для отладки MPI/OpenMP и DVM/OpenMPпрограмм. Особенностью созданных программных средств является небольшой размер получаемой трассы, независящий от числа итераций циклов исходной программы, незначительное замедление анализируемой программы и совместимость характеристик с анализатором системы DVM.
1. Бахтин В.А. Интерфейс инструментации Fortran DVM/OpenMP-программ
[doc](http://www.keldysh.ru/dvm/omp/OpenMPInstr.doc)
2. NAS PARALLEL BENCHMARKS
[html](http://www.nas.nasa.gov/Resources/Software/npb.html)
3. Отладка эффективности параллельных программ. Руководство пользователя.
[html](http://www.keldysh.ru/dvm/dvmhtm1107/rus/usr/perform/pppaUGr.html)
4. OpenMP Application Program Interface
[pdf](http://www.openmp.org/mp-documents/spec30.pdf)
5. KOJAK Trace-Analysis Environment
[html](http://icl.cs.utk.edu/kojak/kojak)
6. Intel Thread Profiler Product In-Depth
[pdf](http://software.intel.com/en-us/intel-vtune/intel_thread_profiler_ondepth.pdf)
7. Karl Furlinger, Michael Gerndt. ompP: A Profiling Tool for OpenMP
[pdf](www.lrr.in.tum.de/~gerndt/home/Vita/Publications/05iwomp.pdf)
8. Automatic Performance Analysis: Resources and Tools
[ppt](http://www.lrr.in.tum.de/~gerndt/home/Vita/Presentations/2003/APARTSC03.ppt)
9. Bernd Mohr . OpenMP Pragma And Region Instrumentor
[html](http://www.fz-juelich.de/jsc/kojak/opari/)
10.Performance Profile Parallel MPI and OpenMP Applications
[html](http://www.pgroup.com/products/pgprof.htm)
11. John Levon. OProfile manual
[html](http://oprofile.sourceforge.net/doc/index.html)
12.What is Mono
[html](http://www.mono-project.com/What_is_Mono)
13.Суперкомпьютер СКИФ МГУ "ЧЕБЫШЁВ"
[html](http://parallel.ru/cluster/skif_msu.html)
14.Крюков В.А. РАЗРАБОТКА ПАРАЛЛЕЛЬНЫХ ПРОГРАММ ДЛЯ ВЫЧИСЛИТЕЛЬНЫХ КЛАСТЕРОВ И СЕТЕЙ
[html](http://www.keldysh.ru/dvm/dvmhtm1107/publishr/cldvm2002web.htm)
15. DVM система.
[html]( http://keldysh.ru/dvm/dvmhtm1107/rus/index.html)
Контекстная строка представляет собой последовательность пар «атрибут=значение» разделенных звездочками «*».
"<length>*type=<type>*name1=<name>*file=<file>*line1=<number>*...**"
Строка заканчивается пустым полем (двойной звездочкой «**»). Длина строки обязательна, все остальные поля не обязательны. Две звездочки на конце обязательны. Под длиной строки понимается количество символов между первой звездочкой и последней (включая обе), не считая каких-либо завершающих нулей или пустых символов в Фортране. Если звездочка встречается внутри какого-либо поля (например, в выражении клаузы NUM_THREADS), то после нее должен быть вставлен символ слеш (\). Это позволяет однозначно определять границы пар, поскольку ни одно описание типа не может начинаться с символа слеш. Самая короткая строка - «2**».
Используемые функции инструментации:
dbg_init
dbg_finalize
dbg_get_handle
dbg_before_parallel
dbg_parallel_event
dbg_parallel_event_end
dbg_after_parallel
dbg_before_omp_loop
dbg_omp_ifiter
dbg_ompiter
dbg_omp_loop_event
dbg_after_omp_loop
dbg_before_sections
dbg_section_event
dbg_section_event_end
dbg_after_sections
dbg_before_single
dbg_single_event
dbg_single_event_end
dbg_after_single
dbg_before_workshare
dbg_after_workshare
dbg_master_begin
dbg_master_end
dbg_before_critical
dbg_critical_event
dbg_critical_event_end
dbg_after_critical
dbg_before_barrier
dbg_after_barrier
dbg_before_flush
dbg_flush_event
dbg_before_ordered
dbg_ordered_event
dbg_after_ordered
dbg_begsl
dbg_sifiter
dbg_siter
dbg_endsl
dbg_before_func_call
dbg_funcparvar
dbg_funcpararr
dbg_after_func_call
dbg_func_begin
dbg_func_end
dbg_reg_par
dbg_reg_par_arr
dbg_type_controllong
dbg_get_addr
dbg_threadprivate
В первой строке указывается номер нити: Trace for thread <threadnum>
Для главной нити во второй строке записывается Thread is master
Затем идут события и интервалы.
Вначале перечисляются интервалы, затем события. Внутри каждого интервала сначала перечисляются вложенные интервалы, затем вложенные события и так далее для всех уровней вложенности.
Для интервала обозначается начало и конец. Запись в трассе об интервале имеет следующий формат:
B<int_num>:<btime>:<dtime>:<counter>:<avg_dtime>:<max_dtime>
Интервалы и события, вложенные в этот интервал
E<int_num>
Где <int_num> - номер контекстной строки соответствующей интервалу
Для событий создается по одной записи в трассе следующего формата:
<int_num>:<btime>:<dtime>:<counter>:<wtime>:<stime>:<avg_dtime>:<max_dtime>:<avg_wtime>:<max_wtime>:<avg_stime>:<max_stime>
Статистика соответствует описанной в разделе 3.4.
Пример промежуточной трассы в приложении Е.
Protocol
Threads: <numthreads>(<num_master>[M] <list of others threadnums>)
Execution Time: <etime>
Processors: <pnums>
Total Time: <ttime>
Productive Time: <ptime>
Idle Time: <itime>
Lost Time: <ltime>
Insufficient Par: <inspar>
Parallelization Eff:<eff>(eff*100 %)
Desync Time: <stime>
SRCs:
<src_points_list>
End protocol
Характеристики отраженные в протоколе см. в разделе 3.6.
Формат записи точек SRC в протоколе.
Src <num>
Btime=xx
Dtime=xx
MaxDtime=xx
AvgDtime=xx
Wait=xx
MaxWait=xx
AvgWait=xx
Sync=xx
MaxSync=xx
AvgSync=xx
Count=xx
OMP_instance=<fuction or directive name>
Stack:
<filename> (line1:line2) [list of threads]
Параметры между Src и OMP_instanse соответствуют статистике накопленной для события <num> в трассе главной нити. Среднее и максимальное значение статистики выводятся только в случае, если событие повторилось больше одного раза. Btime в этом случае не выдается. Если событие не встречалось в главной нити, то указывается <num>:<threadnum>, где <threadnum> это номер нити, в которой это событие произошло. Если таких нитей несколько, то в качестве номера берется номер любой содержащей событие нити.
OMP_instance содержит информацию о типе события это либо директива OpenMP (barrier, ordered, critical, flush) либо замок.
После stack находится информация о месте в исходном коде, которое соответствует событию и список нитей, в которых это событие встретилось с указанем номера события в трассе соответствующей нити. Пример:
Src.f (13:13) 1354:6 1756:8
Line1 и line 2 обозначают строки файла с исходным кодом. Если событию соответствует одна строка как в примере выше, одна и та же строка указывается два раза.
В читаемую трассу выдаются события и интервалы.
Формат для интервалов:
<номер интервала> user interval begins имя интервала src=filename(line1:line2) статистика
…
<номер интервала> user interval ends имя интервала src=filename(line1:line2) статистика
Формат для событий:
<номер события> <тип события> src=filename(line1:line2) статистика.
Для интервала создается две записи в читаемой трассе, между которыми находятся записи обо всех событиях и интервалах вложенных в данный интервал.
Статистика выдается в формате атрибут=значение. Список атрибутов указан в разделе 3.4.
Номера интервалов и событий такие же как в промежуточной трассе, по которой строится соответствующая читаемая трасса.
Общий формат запуска анализатора:
Manalizer [options]
Ключи(options) делятся на 3 категории:
Преобразование трассы:
-make-all-traces[=name] - создание для каждого файла в текущей директории с именем в формате name.thrednum.mtr (name можно задавать, по умолчанию trace; threadnum номер нити - число), файла с тем же именем и расширением rtr, содержащего полную читаемую трассу либо неполную при указании общих ключей.
-make-trace <имя файла> - как make-all-traces для одного файла.
С ключем make-trace и только с ним можно использовать ключ event=<eventnum>, где <eventnum> номер события в трассе. При использовании этого ключа анализатор выдает в stdout читаемую трассу содержащую одно это событие.
Анализ:
-analize-with-traces[=name] создание протокола и читаемой трассы для всех файлов в текущей директории с именами в формате указанном в описании опции make-all-traces.
-analize выдача только протокола, если не указаны ключи - считается указанным по умолчанию.
-main-thread=<threadnum> - считать главной нить с номером <threadnum>
Общие ключи для обоих режимов:
-no-events=evnum[,evnum] не учитывать указанные события при анализе или построении читаемой трассы.
-no-intervals=interv[,interv] то же для интервалов и входящих в них событий
-intervals=interv[,interv] производить анализ или преобразование трассы только для указанных интервалов.
Общие ключи могут стоять только перед ключами для анализа или преобразования трассы. Нельзя указывать одновременно ключи для разных режимов работы. Если ключи не указаны, то по умолчанию считается указанным ключ analize.
В качестве демонстрации использован тест NAS EP класса B
Фрагмент исходного текста после инструментирования:
call dbg_before_parallel(istat_mp(5),ithreadid,(-1),(-1))
!$OMP PARALLEL
call dbg_parallel_event(istat_mp(5),ithreadid)
call dbg_before_funcall(istat_mp(6),ithreadid)
call timer_clear(1)
call dbg_after_funcall(istat_mp(6),ithreadid)
if (timers_enabled) then
call dbg_before_funcall(istat_mp(7),ithreadid)
call timer_clear(2)
call dbg_after_funcall(istat_mp(7),ithreadid)
endif
if (timers_enabled) then
call dbg_before_funcall(istat_mp(8),ithreadid)
call timer_clear(3)
call dbg_after_funcall(istat_mp(8),ithreadid)
endif
call dbg_parallel_event_end(istat_mp(5),ithreadid)
!$OMP END PARALLEL
call dbg_after_parallel(istat_mp(5),ithreadid)
call dbg_before_funcall(istat_mp(9),ithreadid)
call timer_start(1)
call dbg_after_funcall(istat_mp(9),ithreadid)
t1 = a
call dbg_before_funcall(istat_mp(10),ithreadid)
call vranlc(0,t1,a,x)
call dbg_after_funcall(istat_mp(10),ithreadid)
Фрагмент промежуточной трассы главной нити для класса B
16 B140734041842640:1269:7643:1:0:0
17 B81604378642:7582:834:2048:0:0
19 E81604378642
20 51539607563:1269:0:1:0:1269:0:0:0:0:1269:1269
21 55834574860:1269:0:1:0:1269:0:0:0:0:1269:1269
22 60129542157:1269:6316:1:0:7585:6316:6316:0:0:7585:7585
23 64424509454:1269:0:1:0:1269:0:0:0:0:1269:1269
24 73014444048:7582:3:2049:0:9113329:3:0:0:0:9113329:5788443
25 94489280533:7583:5479:2048:0:9110011:5479:4163:0:0:9110011:5798203
26 103079215127:7585:0:1:0:7584:0:0:0:0:7584:7584
27 107374182424:7585:0:10:0:75840:0:0:0:0:75840:47516
28 111669149721:8912:0:1:0:8912:0:0:0:0:8912:8912
30 E140734041842640
Протокол для класса B (без точек SRC) для одного интервала:
Protocol
Threads: 8( 8543[M] 8545 8546 8547 8548 8549 8550 8551)
Execution Time: 6451
Processors: 8
Total Time: 51608
Productive Time: 47368
Idle Time: 0
Lost Time: 4240
Insufficient Par: 3864
Parallelization Eff:91784(91,784 %)
Desync Time: 146
Idle time равно нулю т.к. проанализирован только один интервал.
Фрагмент читаемой трассы
16 sequential loop src=dbg_ep.fdv (187:193) counter=192 dtime=3186(395) avgdtime=2 maxdtime=3
17 function call timer_start src=(198:198) counter=1 dtime=0(0) avgdtime=0 maxdtime=0
Нулевые значения в 17 событии из-за того, что время однократного выполнения функции timer_start меньше одной миллисекунды. В событиях нет другой статистики, т.к. для данных типов событий имеют смысл только приведенные.
А также другие работы, которые могут Вас заинтересовать | |||
56178. | «Більше, сильніше, швидше». Олімпійські ігри. Спорт | 48.5 KB | |
Today we’re going to talk to learn about the Olympic Games and we’ll discuss it. You will listen to the text about the Olympic Games and do some tasks, discuss famous Ukrainian spotsman. So, let’s start. | |||
56179. | ВИГОТОВЛЕННЯ ІГРАШОК-СУВЕНІРІВ “СПОРТСМЕНИ“ | 56.5 KB | |
Із поролону вирізати деталі: тулуб разом із головою та ноги. Із коричневого драпу вирізати деталі тулуба й ніг. Зєднати деталі тулуба із тканини й поролону зметати й зшити косим стібком через край. Зєднати деталі із тканини й поролону зметати й зшити. | |||
56181. | Німецька мова — одна з найкращих європейських мов | 145.5 KB | |
Stimmt. Ich bin damit einverstanden. Auβerdem werden wir H?rverstehen?ben, Sprachreaktion entwickeln, die Liebe zur deutschen Sprache beitragen. Jetzt beginnen wir mit der Wortschatzarbeit. | |||
56184. | Справочник юного натуралиста | 977.5 KB | |
Сельским жителям лесостепных районов УССР известна эта небольшая серая птица с коричневой подковкой на груди. Дятел Дятлы тоже принадлежат к лазающим птицам в полном смысле этого слова и при лазанье по коре деревьев очень ловко умеет пользоваться парным расположением своих пальцев. | |||
56185. | ЧЕЛОВЕК И ОКРУЖАЮЩАЯ СРЕДА | 190.5 KB | |
Развивать интуицию память речь умение логически мыслить делать выводы. Вечное как мир: с чего начинается Родина маминой песни родительского дома или рисунка букваре Изменения Положительные Отрицательные Воды Почвы Население Атмосфера... | |||
56186. | The Structure and Functions of British Parliament | 103.5 KB | |
The British Parliament works in a large building called the Palace of Westminster (popularly known as the Houses of Parliament). This contains offices, committee rooms, restaurants, bars, libraries and even some places of residence. | |||