поддерживаю выше заданые вопросы
|
Введение в использование инструментов для параллельного программирования на примере пакета Intel Parallel Studio
Цель лекции: Лекция направлена на знакомство слушателей с ошибками, возникающими в параллельных программах с приведением способов их избегания и решения с помощью инструментов Intel.
Видеозапись лекции - (объем - 156 МБ).
6. Введение в отладку параллельных программ в системах с общей памятью
Ни для кого не секрет – наличие инструментов делает жизнь проще. Тезис этот находит подтверждение как в повседневной жизни (чистить одежду удобнее и эффективнее щеткой, чем руками, заворачивать гайки гораздо проще ключом, чем пальцами), так и в профессиональной деятельности (кто сейчас возьмется строить, ладно, даже не дом, пусть всего лишь баню, при помощи одного лишь топора?!). Естественно, программисты – не исключение. Значение инструментов, облегчающих путь от анализа постановки задачи до получения решения, готового к внедрению, трудно переоценить. В данном кратком описании представлен инструмент отладки параллельных программ, разработанный корпорацией Intel и носящий название Intel® Thread Checker.
В п. 6.1 приводится назначение рассматриваемого инструмента, характеризуются области его возможного применения. В п. 6.2 дается краткая характеристика принципов работы Intel® Thread Checker. В пп. 6.3 – 1.5 приводится информация, необходимая для подготовки пользовательского проекта и инструмента для анализа. П. 6.6 посвящен вопросам сбора и анализа данных, полученных в результате работы Intel® Thread Checker. В п. 6.7 возможности инструмента рассмотрены на простом примере, входящем в поставку Intel® Thread Checker.
6.1. Назначение Intel Thread Checker
Процесс отладки в общем случае можно разбить на следующие шаги:
- определение факта наличия ошибки;
- поиск (локализация) ошибки;
- выяснение причин ошибки;
- определение способа устранения ошибки;
- устранение ошибки.
Кажется, что на первом шаге никакой инструмент не требуется. Запускаем программу и либо на некоторых исходных данных получаем неверные результаты, либо обнаруживаем, что некоторая последовательность действий по использованию программы ведет к ее "падению" или "зависанию". Однако для параллельной программы даже этот очевидный шаг может иметь существенную сложность. На практике нередко встречаются ситуации, когда неработоспособность параллельной программы проявляется один раз на сотню и более запусков. Очевидно, в этом случае инструментальная поддержка лишней не будет.
Назначение Intel® Thread Checker (ITC) – поиск мест с возможным недетер минированным поведением многопоточной программы, написанной как на основе библиотеки потоков (Windows или POSIX threads), так и с использованием технологии OpenMP. Соответственно ITC может быть использован под операционными системами как семейства Windows, так и семейства Linux. Принципы поиска ошибок рассмотрены ниже, здесь же укажем, что ITC неплохо справляется с задачей обнаружения факта ошибки в программе, даже если эта ошибка в текущем варианте исполнения программы и не проявила себя.
Второй шаг – поиск ошибки – заключается в как можно более точной ее ло кализации; в идеале должна быть найдена переменная с неверным значением и/или строка кода, ведущая к краху программы. Типичный метод работы в этом пункте – использование режима трассировки в отладчике с наблюдением за состоянием переменных, регистров, стека вызова и т.д. "Плохая новость" – для много- поточных программ режим трассировки практически неприменим, поскольку автоматически меняет характер их выполнения, а значит, скрывает места, которые могут приводить к проблемам во время реальной работы. Кстати говоря, даже типичный способ локализации ошибки расстановкой операторов печати по тексту программы в этом случае нужно использовать с большой осторожностью – печать также вносит синхронизацию в выполнение программы.
Что же делать? Быть может, наилучшее из возможных решение реализовано в ITC. ITC не есть привычный всем отладчик с режимами трассировки, наблюдения и т.д. ITC выполняет анализ программы сам, без участия программиста, причем анализируется не только выполненный "прогон" программы, а все возможные варианты ее выполнения. В результате выясняются и показываются программисту места в программе, в которых содержатся ошибки (с той или иной долей вероятности, в большинстве случаев близкой к 100%).
Шаг третий – выяснение причин ошибки. Задача здесь – понять, почему ошибка возникла. Отсюда во многих случаях автоматически вытекает способ ее устранения (задача шага четвертого). Можно, конечно, выяснить условия, ведущие к проявлению ошибки (некое сочетание значений переменных, например), и просто вставить в код заплатку именно для этого случая. Данный вариант мы здесь не рассматриваем. На этом шаге ITC помогает тем, что каждое найденное им проблемное место сопровождает комментарием, содержащим тип ошибки: гонка дан- ных, несинхронизированный доступ к переменной, тупик и т.д.
В результате мы получаем место потенциальной ошибки, переменную, с которой связана проблема, и описание ошибки. Остается лишь освоить типовые способы борьбы с типовыми ошибками – и значительная их часть будет находиться и исправляться без грандиозных усилий.
Единственное, в чем ITC совсем не может помочь – это шаг пятый. Устранять найденную ошибку все-таки придется программисту самостоятельно.
6.2. Возможности Intel Thread Checker
Согласно [2] ITC обнаруживает ошибки следующих видов: гонки данных (data races), тупики (deadlocks), потоки в состоянии ожидания (stalled threads), потерянные сигналы (lost signals), заброшенные замки (abandoned locks).
Приведем краткое описание каждого вида.
- Гонки данных. Возникают, когда несколько потоков работают с разделяемыми данными и конечный результат зависит от соотношения скоростей потоков. Пусть, например, один поток выполняет над общей переменной x операцию x = x + 3, а второй поток – операцию x = x + 5. Данные операции для каждого потока фактически разбиваются на три отдельные подоперации: считать x из памяти, увеличить x, записать x в память. В зависимости от взаимного порядка выполнения потоками подопераций финальное значение переменной x может быть больше исходного на 3, 5 или 8. Гонка данных возможна и в случае, когда один поток пишет в перемен ную, а остальные только читают из нее.
- Тупики. Взаимная блокировка потоков, ожидающих наступления некоторого события для продолжения работы. Типичный пример тупика: нулевой поток занял для использования ресурс 1 и ожидает предоставления ему ресурса 2, а первый поток занял ресурс 2 и ожидает предоставления ему ресурса 1.
- Потоки в состоянии ожидания. Одно из состояний потока в многозадачной операционной системе – ожидание. Поток переходит в него, когда для продолжения выполнения ему требуется наступление некоторого внешнего события. Если пребывание потока в этом состоянии продолжается слишком долго, ITC рапортует об ошибке типа stalled thread. Интервал времени, по истечении которого выдается данная диагностика, может быть задан в настройках ITC.
- Потерянные сигналы. Возникают, когда поток ожидает наступления некоторого события, произошедшего прежде, чем поток пришел в состояние готовности к его приему и обработке. В результате поток никогда не сможет выйти из состояния ожидания.
- Заброшенные замки. Возникают в ситуации, когда поток захватил некоторый ресурс (критическую секцию, мьютекс) и был снят с выполнения по той или иной причине. В результате ресурс не может быть освобожден. Если он требуется другому потоку, это приведет к бесконечному ожиданию.
6.3. Принцип сбора информации
Анализ программы, выполняемый ITC, основан на процедуре инструментации. Инструментация – вставка обращений к библиотеке ITC для записи дей- ствий, потенциально способных привести к ошибкам: работа с памятью, вызовы операций синхронизации и работа с потоками [2]. Может выполняться автоматически на уровне исполняемого модуля (а также dll-библиотеки) и/или по указанию программиста на уровне исходного кода. Для достоверности получаемых результатов крайне желательно, чтобы во время сборки анализируемой программы была выключена оптимизация (сборка в конфигурации debug необязательна).
В процессе анализа контролируются:
- доступ к памяти;
- операции синхронизации;
- операции создания потоков.
Необходимо отметить, что неисполняемые участки (невызываемые функции, ветки условных переходов и т.д.) никак не проверяются, то есть под анализ не подпадают.
6.4. Подготовка программы для анализа
Использование отладчика Intel® Thread Checker возможно в двух режимах:
- Бинарная инструментация программы – осуществляется автоматически в момент запуска Активности (Activity)1Активность – термин из среды VTune, в рамках которой работает ITC. Фактически представляет собой "контейнер", содержащий, с одной стороны, настройки системы и параметры анализируемой программы, с другой – результаты проводимого анализа. в проекте ITC. Рекомендуется в случае, если отсутствует доступ к исходным кодам или невозможна повторная сборка программы с нужными ITC настройками.
- Компиляторная инструментация – при сборке анализируемой программы необходимо указать ключ компилятора /Qtcheck. Позволяет ITC предоставить информацию о найденных ошибках с указанием имен переменных, с которыми эти ошибки связаны.
Сборка приложения для работы с ITC предполагает установку следующих опций проекта (или настроек в make-файле):
- Компиляция потокобезопасного кода: -MT[d], -MD[d]. Данные опции автоматически устанавливаются при сборке в конфигурации debug. При сборке в конфигурации release указанные опции необходимо устанавливать вручную.
- Использование debug-опций: -Z[i,I,7], -Od. Замечание аналогично предыдущему пункту.
- Связывание с ключом /fixed:no. Необходимо указывать явно.
Дополнительно необходимо отметить, что при использовании ключа /Qtcheck в среде разработки (IDE) требуется указать путь к библиотекам ITC. Обычно этот путь имеет вид C:\Program Files\Intel\VTune\Analyzer\Lib\.
6.5. Создание проекта в Intel Thread Checker
Работа в ITC выполняется в рамках проекта. Для его создания используется команда меню File →New Project. В главном окне мастера настройки проекта (см. рис. 6.1) необходимо выполнить всего лишь два действия. Первое – указать исполняемый файл (Launch an application). Второе (необязательное) – указать аргументы командной строки.
Рекомендуется при анализе программы, с одной стороны, использовать типичные размеры обрабатываемых данных, с другой – задавать их так, чтобы программа "убиралась" в оперативную память с учетом накладных расходов ITC, которые могут быть довольно значительными.
6.6. Сбор и анализ данных
После запуска в проекте ITC активности (при создании проекта это происходит автоматически) начинается инструментация исполняемого модуля, указанного для анализа, и используемых им динамических библиотек. Затем модуль запускается и начинается процесс анализа. По завершении ITC формирует окно с информацией о найденных ошибках и подозрительных местах. Возможный его вид указан на рис. 6.2.
В случае повторного запуска активности необходимо использовать один из следующих вариантов: 1) выбрать пункт меню Activity → Run; 2) нажать F5; 3) нажать кнопку на панели инструментов
По каждой диагностике, выданной ITC, в случае если сборка выполнялась с приведенными в пункте 1.4 настройками, может быть получена дополнительная информация (см. пункт 1.7), вид которой показан на рис. 6.3.