При написании и отладке программ в OpenMP необходимо обеспечить выполнение целого ряда специфических требований, без которых невозможно гарантировать корректность работы программы. Далее рассмотрим эти требования подробнее.
Во-первых, необходимо обеспечить, чтобы все используемые в программах библиотеки были безопасны с точки зрения потокового выполнения. При этом следует иметь в виду, что все стандартные библиотеки всегда удовлетворяют этому требованию. Таким образом, важно обеспечить выполнение этого требования только по отношению к тем библиотекам, которые создает сам разработчик или его коллеги.
Разрабатывая и отлаживая программы в OpenMP, необходимо помнить, что операции ввода/вывода в параллельных потоках завершаются в непредсказуемом порядке. Поэтому большое внимание следует уделять проблеме синхронизации параллельных процессов, помня при этом, что синхронизация - очень дорогая операция. Поэтому ею следует пользоваться как можно реже и только в случае крайней необходимости.
При разработке программ с использованием OpenMP следует внимательно прослеживать пересечение локальных переменных типа private в параллельных потоках с глобальными переменными. Кроме того, необходимо тщательно отслеживать своевременное обновление значений переменных в общей памяти. Для этого по мере необходимости следует пользоваться директивой OpenMP flush.
Проектируя программы, следует помнить, что удалить неявно установленные барьеры ( ) в операторах цикла можно с помощью предложения OpenMP .
При работе программ с общей памятью возникает ряд специфических ошибок, одна из которых связана с так называемыми условиями состязательности ( conditions ). Ошибки, связанные с условиями состязательности, состоят в непредсказуемом времени завершения параллельных потоков, из-за чего возможны непредсказуемые результаты вычислений. Автоматическое распараллеливание в таких ситуациях затруднено, поскольку компилятору либо трудно, либо вообще невозможно распознать взаимозависимости по данным, возникающие в процессе параллельных вычислений при непредсказуемом времени завершения работы параллельных потоков. В таких ситуациях важно правильно определить последовательность выполнения параллельных потоков, чтобы избежать непредсказуемых результатов.
В качестве примера возникновения условия состязательности рассмотрим фрагмент программы, показанный в примере 5.1.
c$omp parallel sections
A = B + C
c$omp section
B = A + C
c$omp section
C = B + A
c$omp end parallel sections
Результат вычислений в этом примере будет зависеть от того, в какой последовательности выполняются параллельные потоки. При этом никакой диагностики компилятора о возникновении условия состязательности в программе не выдается. Это существенно усложняет отладку параллельных приложений, если программист заранее не позаботится об исключении таких ситуаций. Устранить некорректность в вычислениях в рассматриваемом примере можно, например, с помощью синхронизации параллельных потоков или с помощью директив загрузки параллельных процессов в OpenMP. Ниже в примере 5.2 приведен пример одной из возможных модификаций фрагмента программы (пример 5.1), в котором устранены недостатки, связанные с наличием условия состязательности. В этой модификации для предотвращения условия состязательности введен счетчик событий ICOUNT и использована директива OpenMP FLUSH для организации корректного обращения к данным. Счетчик
событий ICOUNT устанавливает последовательность вычислений: сначала вычисляется A=B+C, потом B=A+C и лишь затем C=B+A. Использование сочетания операторов IF и GOTO в сочетании с директивой OpenMP FLUSH позволило в этом примере провести синхронизацию трех параллельных процессов.
Еще один пример возникновения условия состязательности в программе представлен во фрагменте в примере 5.3. В этом примере условие состязательности возникает из-за неправильного в данном случае использования предложения OpenMP . Для корректной работы программы достаточно просто исключить предложение .
ICOUNT = 0
c$omp parallel sections
А = В + С
ICOUNT = 1
c$omp flush ICOUNT
c$omp section
1000 CONTINUE
c$omp flush ICOUNT
IF (ICOUNT .LT. 1)GOTO 1000
B = A + C
ICOUNT = 2
c$omp flush ICOUNT
c$omp section
2000 CONTINUE
c$omp flush ICOUNT
IF (ICOUNT .LT. 2)GOTO 2000
C = B + A
c$omp end parallel sections
c$omp parallel shared (X)
c$omp private (TMP)
ID=omp_get_thread_num ()
c$omp do reduction (+ : X)
DO 100 I = 1, 100
TMP = WORK(I)
X = X + TMP
100 CONTINUE
c$omp end do nowait
Y( ID ) = X
c$omp end parallel
В примере 5.4 условия состязательности можно избежать, описав переменную TMP в параллельной области как private.
REAL TMP, X
c$omp parallel do reduction (+ : X)
DO 100 I = 1, 100
TMP = WORK(I)
X = X + TMP
100 CONTINUE
c$omp end do
Y(ID) = X
c$omp end parallel
В процессе выполнения программ с общей памятью возможна ситуация, когда один из параллельных потоков ожидает освобождения доступа к объекту, который никогда не будет открыт. Такая ситуация, возникающая в параллельной программе, называется мертвой блокировкой ( deadlock ).
В качестве иллюстрации мертвой блокировки рассмотрим фрагмент программы на языке Fortran, приведенный в примере 5.5.
call omp_init_lock (lcka)
call omp_init_lock (lckb)
c$omp parallel sections
call omp_set_lock (lcka)
call omp_set_lock (lckb)
call useAandB (res)
call omp_unset_lock (lckb)
call omp_unset_lock (lcka)
c$omp section
call omp_set_lock (lckb)
call omp_set_lock (lcka)
call useBandA (res)
call omp_unset_lock (lcka)
call omp_unset_lock (lckb)
c$omp end parallel sections
В этом примере при выполнении параллельных потоков возможна ситуация, когда объект А заблокирован в одном параллельном потоке, а объект В - в другом. В результате возникает мертвая блокировка и выполнение подпрограмм useAandB и useBandA не происходит. Однако это не единственная неприятная ситуация, возникающая в этой программе.
Возможно, что при выполнении параллельных потоков в одном потоке окажутся заблокированными оба объекта A и B, тогда при выполнении рассматриваемой программы возникает условие состязательности, рассмотренное в предыдущем разделе данной лекции. Для исправления возникшей в программе ошибочной ситуации следует избавиться от различных вложенных блокировок.
Рассмотрим еще один пример мертвой блокировки, который возможен при работе программы, показанной в примере 5.6.
call omp_init_lock (LCKA)
c$omp parallel sections
c$omp section
call omp_set_lock (LCKA)
IVAL = dowork ()
if (IVAL .EQ. TOL) then
call omp_unset_lock (LCKA)
else
call error (IVAL)
endif
c$omp section
call omp_set_lock (LCKA)
call use_B_and_A (RES)
call omp_unset_lock (LCKA)
c$omp end sections
В этом примере при выполнении параллельных потоков возможно возникновение как мертвой блокировки, так и условия состязательности.
Мертвая блокировка возникает, если в первом параллельном потоке установлена блокировка объекта A, а IVAL не равно TOL.
В этом случае установить блокировку объекта A во втором параллельном потоке невозможно, поскольку программа ждет отмены блокировки, установленной в первом параллельном потоке.
Если же в первом параллельном потоке установлена блокировка объекта A, а IVAL равно TOL, то в программе возникает условие состязательности.
Для исправления возникшей ситуации необходимо устранить не только мертвую блокировку, но и условия состязательности.
Актуальность развития многопоточных приложений обусловлена быстрым развитием и все более широким распространением микропроцессоров, реализующих многоядерные (multicore) и многопоточные (
Поскольку многопоточная программа существенно сложнее однопоточной, вести отладку таких приложений весьма и весьма непросто. Применение обычных (стандартных) отладчиков не может решить и малой доли проблем, возникающих при отладке многопоточных приложений. Поэтому становится весьма актуальной задача создания автоматизированных средств отладки с наглядным графическим интерфейсом. Одним из таких средств является разработка компании Intel - программа Intel Thread Checker. Эта программа имеет развитый графический интерфейс и позволяет быстро и эффективно решать основные проблемы отладки многопоточных программ, находя и устраняя сложные, невидимые на первый взгляд ошибки.
С помощью программы Intel Thread Checker разработчик может в автоматическом режиме осуществить поиск ошибок в многопоточной программе, проанализировать условия доступа к данным в параллельных потоках, выявить тупиковые ситуации в программе и установить причины зависания потоков. Кроме того, с помощью этого инструмента разработчик может провести модернизацию параллельной программы, руководствуясь подсказками программы Intel Thread Checker.
Программа Intel Thread Checker работает под управлением операционных систем Windows и Linux и позволяет вести отладку с Windows-компьютера на удаленных Linux-компьютерах.
В процессе анализа программы разработчика программа Intel Thread Checker находит строки текста с ошибками и отмечает сами ошибки. Кроме того, программа Intel Thread Checker находит некорректно используемые переменные и их описания. Справочная система программы не только отображает причины найденных ошибок, но и предлагает возможные пути их устранения.
Программа Intel Thread Checker под управлением операционной системы Windows работает в среде разработки с любыми компиляторами компаний Intel и Microsoft. Кроме того, Intel Thread Checker работает в среде разработки Microsoft Visual Studio .NET и позволяет анализировать программы, оттранслированные с помощью следующих версий компиляторов Microsoft: Visual C++ .NET Compiler версий 2002 или 2003, а также Visual C++ Compiler 6.0. Программа поддерживает анализ стека вызовов, функций интерфейса Win32 API, исполняемых библиотек языка C, директив OpenMP. Таким образом, анализ охватывает большинство проблем, с которыми на практике сталкивается разработчик многопоточных программ.
Программа Intel Thread Checker позволяет выводить информацию об ошибках с различными уровнями детализации. Всего в программе имеется шесть различных уровней детализации сообщений об ошибках: от ошибок и предупреждений до содержательных комментариев. Все возникающие ошибки можно классифицировать по категориям, присвоив им определенный статус. Список ошибок можно отсортировать различными способами, например по степени их важности. Затем можно установить причины ошибок и даже получить рекомендации по их устранению. Все это реализовано в удобном графическом режиме.
Программа Intel Thread Checker позволяет не только находить, анализировать и исправлять ошибки в многопоточных параллельных программах, но и анализировать полный ход выполнения программы, находя и выделяя критические пути. Последующий анализ критического пути выполнения многопоточной программы позволяет установить ее узкие места ( bottle neck ), устранить их и тем самым повысить быстродействие программы.
Программа Intel Thread Checker полностью совместима с технологией OpenMP. Однако при этом она может обнаруживать и ошибки в однопоточной версии программы. Для отображения дополнительных сведений об указателях при запуске компилятора следует использовать настройку /Qtcheck компилятора Intel.
Если режим OpenMP не используется, программа Intel Thread Checker распознает практически все многопоточные версии стандартных функций Win32 API и языка C/C++. Так, программа определяет время создания, временной остановки и время прерывания потоков. Кроме того, она выделяет fiber ), критические участки ( critical paths ), функции событий, сблокированные ( ), объекты синхронизации, пулы потоков, функции синхронизации и другие.
На рис.5.1 схематически изображена поэтапная схема проектирования параллельной программы с перечислением инструментов, которые могут быть применены на каждом из этапов.
Как видно из этой схемы, на этапе разработки параллельной программы в качестве средств разработки могут использоваться компиляторы Intel и программа Intel VTune Performance Analyzer; на этапе тестирования и отладки - программа Intel Thread Checker и тесты разработчика; на этапе настройки - программы Intel VTune Performance Analyzer и Intel Thread Profiler. Отметим, что программы Intel Thread Checker, Intel VTune Performance Analyzer и Intel Thread Profiler входят в состав пакета программ Intel Threading Tools. Программа Intel VTune Performance Analyzer является инструментом настройки производительности программ, а программа Intel Thread Profiler - инструментом настройки работы параллельных потоков.
(рис 5.1) Поэтапная схема проектирования параллельной программы и средства разработки, используемые на этапах На рис.5.2 изображено окно запуска и настройки программы Intel Thread Profiler.
После запуска в программе Thread Profiler можно выбрать один из четырех видов графического представления информации:
Определив Activity (различные реализации программы), можно перейти к анализу графической информации, соответствующей анализируемой версии программы.
(рис 5.2) Открытие проекта и выбор настроек в программе Intel Thread Profiler На рис.5.3 показан экран общего вида путеводителя по проекту в программе Thread Profiler.
(рис 5.3) Экран общего вида путеводителя по проекту в программе Intel Thread Profiler На этом экране в сжатой форме представлены три основных окна программы: Bar Chart (диаграмма полос), Speedup Plot (диаграмма ускорения) и Legend (условные обозначения). Закладки Data, Threads, Regions позволяют осуществить более подробный анализ работы исследуемой программы.
На рис.5.4 представлен подробный анализ диаграммы полос (Bar Chart) для исходной (A0) и модифицированной (A1) версий исследуемой программы в Intel Thread Profiler.
(рис 5.4) Анализ диаграммы для исходной (A0) и модифицированной (A1) версий исследуемой программы в Intel Thread Profiler Как видно из этого рисунка, в исходной версии программы установлен дисбаланс потоков, устранить который можно после модификации программы.
Теперь рассмотрим основные моменты запуска и работы с программой Intel Thread Checker. На рис.5.5 показаны этапы создания нового проекта.
После запуска программы Intel Thread Checker на экране появляются окна с результатами анализа исследуемой программы (см. рис.5.6). Нажав на красный флажок в верхней строке меню, увидим следующую картину:
Эта картина иллюстрирует анализ загрузки памяти, полученный с помощью программы Intel Thread Checker. Щелкнув левой клавишей мыши на одной из функций в графе Context, можно открыть окно с ассемблерным текстом выбранной функции, а также с текстом на языках C/C++ или Fortran. Это окно показано на рис.5.7. Далее можно выбирать различные режимы просмотра и анализа процессов в параллельной программе. В качестве примера на рис.5.8 приведена трассировка стека в анализируемой программе.
(рис 5.5) Создание нового проекта в программе Intel Thread Checker
(рис 5.6) Анализ загрузки памяти в программе Intel Thread Checker
(рис 5.7) Анализ загрузки памяти в программе Intel Thread Checker
(рис 5.8) Анализ трассировки стека в программе Intel Thread Checker В заключение этого раздела скажем, что интерфейс программы Intel VTune Performance Analyzer аналогичен уже рассмотренному интерфейсу программы Intel Thread Profiler. Также отметим, что были рассмотрены лишь интерфейсы программ, работающих в операционной системе Windows. Для аналогичных программ, работающих в операционной системе Linux, пока не разработано единой графической оболочки. Запуск этих программ в операционной системе Linux в настоящее время осуществляется из командной строки с помощью специальных настроек. Результаты работы программ записываются в специальный раздел на жестком диске, и лишь затем можно запустить программы для просмотра в графическом режиме полученных результатов.
Наличие современных автоматизированных средств отладки многопоточных программ не устраняет необходимости использования в процессе разработки и обычных средств отладки - сервисных программ-отладчиков. Однако стандартные отладчики ddd, idb и т. п. не очень удобны для многопоточных приложений, поскольку разрабатывались в основном для приложений однопоточных. На рынке системного программного обеспечения существуют и специальные отладчики, предназначенные для отладки многопоточных приложений. К ним как раз и относится отладчик TotalView, разрабатываемый и поддерживаемый компанией Etnus. Он ориентирован в первую очередь на анализ и настройку многопоточных параллельных программ. Отладчик TotalView - коммерческий продукт, и для работы с ним нужно приобрести лицензию. Однако существует и его бесплатная учебная версия, позволяющая отлаживать параллельные программы, в которых реализуется до 8 параллельных потоков. Далее подробнее остановимся на возможностях этого отладчика.
(рис 5.9) Основное окно отладчика TotalView После запуска отладчика из командной строки операционной системы Linux на экране компьютера появляется основное окно программы, изображенное на рис.5.9.
Загрузить программу для отладки можно в меню File. После загрузки можно начать отладку, например, воспользовавшись командой Step, которую можно найти на второй сверху панели инструментов. Кроме того, можно в окне просмотра текста программы установить курсор на нужную строку и нажать на кнопку Run To на панели инструментов отладчика TotalView. В результате программа выполнится до той строки, на которой установлен курсор. Еще один способ запуска программы под управлением отладчика состоит в расстановке точек прерывания (Break Points). Для установки точки прерывания надо щелкнуть левой кнопкой мыши на номере строки в окне просмотра программы. В результате в окне просмотра вместо номера строки появится желтая стрелка на красном фоне (обозначение точки прерывания). Действуя аналогичным образом, можно расставить точки прерывания по всей отлаживаемой программе. Затем, нажимая на кнопку Go на панели инструментов, можно пройти по всей программе с остановками в точках прерывания.
Отметим, что в этом диалоговом окне можно определять не только функции, но и любые вычисления с переменными программы, определенными в точке активности. При этом в диалоговом окне надо задать алгоритмический язык, на котором написана программа, нажав соответствующую кнопку выбора (Check Box), а также активировать кнопку Evaluate.
(рис 5.10) Диалог определения функции print в точке активности Просматривать значения переменных в точке прерывания можно в окнах Stack Trace и Stack Frame в основном окне отладчика, изображенном на рис.5.10. В нижнем фрагменте этого окна есть возможности для идентификации параллельного потока, в котором просматриваются переменные, а также средства перелистывания потоков. Щелчки левой кнопки мыши на данных в окне Stack Frame инициируют открытие всплывающих окон со значениями исследуемых переменных отлаживаемой программы, как показано на рис.5.11.
(рис 5.11) Диалог просмотра значений переменных в TotalView
(рис 5.12) Просмотр значений элементов массива в графическом виде
(рис 5.13) Просмотр и выбор процессов в корневом окне Отметим, что просматривать переменные в TotalView можно не только в числовом виде, как показано на рис.5.11, но и в графическом. Пример просмотра элементов массива в графическом виде изображен на рис.5.12.
При запуске многопоточной программы под управлением отладчика TotalView на экране появляется корневое окно (Root Window) с иерархической информацией по всем запущенным и запускаемым в процессе работы процессам. Вид этого окна представлен на рис.5.13. Все процессы можно разделить на две большие группы: локальные (local) и удаленные (remote). Локальные процессы - это процессы, запущенные на том же процессоре, на котором запущен и сам отладчик. Удаленные процессы запущены на других процессорах. Для отладчика, в принципе, безразлично, какие процессы просматриваются: удаленные или локальные. Программа в основном окне просмотра выводит информацию о них в единообразном виде. Достаточно просто выбрать процесс, как показано на рис.5.13.
В заключение отметим, что более подробно с возможностями отладчика TotalView можно познакомиться, воспользовавшись его документацией.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.