Одним из важнейших
этапов разработки программ является процесс поиска и устранения ошибок,
неизбежно возникающих при написании сложных программных систем. Для того, чтобы
упростить и во многом автоматизировать этот процесс, необходимо использовать
специальные программы, называемые отладчиками. Несмотря на то, что сложность
написания параллельных программ часто существенно превосходит сложность
написания последовательных аналогов, длительное время наблюдалась нехватка
качественных отладчиков для параллельных программ, разрабатываемых с
использованием технологии MPI. Интегрированная среда разработки
Microsoft Visual Studio 2005 имеет в своем
составе отладчик, предоставляющий широкие возможности для поиска и устранения
ошибок, в том числе и для отладки MPI
приложений.
Основные понятия и методы отладки программ в MS VS 2005
Отладка (поиск и устранение ошибок) – один из
важнейших этапов в написании программных систем, часто занимающий у разработчика
больше времени, чем написание отлаживаемого кода. Для того, чтобы максимально
снизить время, затрачиваемое на отладку, необходимо придерживаться рекомендаций
крупнейших производителей программного обеспечения и ведущих исследователей в
области компьютерных наук еще на этапах проектирования и программирования.
Например, подобные рекомендации обычно требуют подготавливать автоматические
тесты для всех участков разрабатываемой системы и контролировать корректность
значений переменных с использованием макроса ASSERT. Но и сама процедура отладки должна
проводиться эффективно, в соответствии с рекомендациями ведущих экспертов в этой
области. Огромное значение здесь имеет правильный выбор отладчика – специальной
программы, существенно упрощающий процесс поиска ошибок, позволяющий выполнять
программу в пошаговом режиме, отслеживать значения переменных, устанавливать
точки остановки и т.д. Важнейшими критериями выбора отладчика являются богатство
предоставляемого программисту инструментария и удобство использования. Отладчик
Microsoft Visual Studio 2005 удачно сочетает в себе оба указанных
качества.
Наиболее частым приемом отладки
является приостановка работы программы в заданный момент времени и анализ
значений ее переменных. Момент, в который программа будет приостановлена,
определяется выбором, так называемых, точек остановки, то есть указанием строк
кода исходной программы, по достижении которых выполнение останавливается до
получения соответствующей команды пользователя. Помимо простого указания строк
кода, где произойдет приостановка, возможно также указание условий, которые
должны при этом выполняться. Например, можно дать указание приостановить
выполнение программы на заданной строке только в том случае, если значение
некоторой переменной программы превысило заданную константу. Правильный выбор
момента остановки имеет решающее значение для успеха отладки. Так, зачастую
анализ значений переменных непосредственно перед моментом падения программы дает
достаточно информации для определения причин некорректной
работы.
Другим исключительно полезным инструментом
является возможность выполнять программу в пошаговом режиме – по одной строке
исходного кода отлаживаемой программы при каждом нажатии пользователем кнопки
F10. При этом пользователь также имеет возможность
заходить внутрь функции, вызов которой происходит на данной строке, или просто
переходить к следующей строке. Таким образом, пользователь всегда находится на
том уровне детализации, который ему необходим.
Для того, чтобы в полной мере оценить
преимущества отладчика, необходимо предварительно скомпилировать программу в
специальной отладочной конфигурации (чаще всего такая конфигурация называется
“Debug”), особенностью которой является добавление в
генерируемые бинарные файлы специальной отладочной информации, которая позволяет
видеть при отладке исходный код выполняемый программы на языке высокого
уровня.
К числу других часто используемых инструментов
отладки Microsoft Visual Studio 2005 относятся:
- Окно “Call Stack” - окно показывает текущий стек вызова
функций и позволяет переключать контекст на каждую из функций стека (при
переключении контекста программист получает доступ к значениям локальных
переменных функции),
- Окно “Autos” - окно показывает значения переменных,
используемых на текущей и на предыдущих строках кода. Кроме того, это окно
может показывать значения, возвращаемые вызываемыми функциями. Список
отображаемых значений определяется средой автоматически,
- Окно “Watch” - окно позволяет отслеживать значения тех
переменных, которых нет в окне “Autos”. Список
отслеживаемых переменных определяется пользователем,
- Окно “Threads” - окно позволяет переключаться между
различными потоками команд процесса,
- Окно “Processes” - окно позволяет переключаться между
различными отлаживаемыми процессами (например, в случае отладки MPI –
программы).
Три подхода к отладке MPI программ
Отладчик
параллельных MPI программ в Microsoft Visual
Studio появился впервые в версии Visual Studio 2005. Однако
компиляцию и отладку MPI программ можно производить и в более
ранних версиях среды разработки. Обычными приемами в случае отсутствия истинной
поддержки MPI со
стороны отладчика являются следующие:
- Использование текстовых
сообщений, выводимых в файл или на экран, со значениями интересуемых
переменных и/или информацией о том, какой именно участок программы
выполняется. Такой подход часто называют “printf отладкой” (“printf debugging”), так как чаще всего
для вывода сообщений на консольный экран используется функция “printf”. Данный подход хорош тем, что он не требует
от программиста специальных навыков работы с каким-либо отладчиком, и при
последовательном применении позволяет найти ошибку. Однако для того, чтобы
получить значение очередной переменной, приходится каждый раз писать новый код
для вывода сообщений, перекомпилировать программу и производить новый запуск.
Это занимает много времени. Кроме того, добавление в текст программы нового
кода может приводить к временному исчезновению проявлений некоторых ошибок,
- Использование последовательного
отладчика. Так как MPI задача состоит из нескольких
взаимодействующих процессов, то для отладки можно запустить несколько копий
последовательного отладчика, присоединив каждую из них к определенному
процессу MPI задания.
Данный подход позволяет в некоторых случаях более эффективно производить
отладку, чем при использовании текстовых сообщений. Главным недостатком
подхода является необходимость ручного выполнения многих однотипных действий.
Представьте, например, необходимость приостановки 32 процессов MPI задания: в случае
использования последовательного отладчика придется переключиться между 32
процессами отладчика и вручную дать команду приостановки.
Параллельный отладчик Microsoft Visual
Studio 2005
лишен указанных недостатков и позволяет существенно экономить время на отладку.
Это достигается за счет того, что среда рассматривает все процессы одной MPI задачи как единую
параллельно выполняемую программу, максимально приближая отладку к отладке
последовательных программ. К числу особенностей параллельной отладки относятся
уже рассмотренное окно “Processes”, позволяющего
переключаться между параллельными процессами, а также дополнительные настройки
среды.
Включение и настройка MPI отладчика в MS VS 2005
Отладчик Microsoft
Visual Studio 2005 наилучшим образом подходит
для работы с MS MPI – реализации
стандарта MPI 2 от
Microsoft. Поэтому,
если Вы хотите в полной мере оценить преимущества отладчика Visual Studio, то необходимо
установить последнюю версию Microsoft Compute
Cluster Pack SDK.
Для того чтобы
получить возможность отлаживать параллельные MPI программы, необходимо
соответствующим образом настроить Microsoft
Visual Studio 2005: выберите пункт меню “Project->project Properties…” и затем в открывшемся
окне настроек проекта выберите пункт “Configuration
Properties->Debugging”. Введите следующие
настройки:
- В поле “Debugger to launch”
выберите “MPI Cluster
Debugger”,
- В поле “MPIRun Command” введите “mpiexec.exe” – имя
программы, используемой для запуска параллельной MPI программы,
- В поле “MPIRun Argument” введите аргументы
программы “mpiexec.exe”. Например, введите “-np <число процессов
designtimesp=14365 designtimesp=14534 designtimesp=14654 designtimesp=14808
designtimesp=14954 designtimesp=15342 designtimesp=15466 designtimesp=15780
designtimesp=16557>” для указания числа процессов, которые будут
открыты,
- В поле “Application
Command”
введите путь до исполняемого файла программы,
- В поле “Application
Argument”
введите аргументы командной строки запускаемой программы,
- В поле “MPIShim Location” введите путь до “mpishim.exe”
– специальной программы, поставляемой вместе с Microsoft Visual Studio 2005,
используемой для отладки удаленных программ,
- Нажмите “OK” для сохранения
внесенных изменений.

Процесс отладки MPI программ в среде MS VS 2005
Отладка параллельных MPI программ имеет ряд особенностей, обусловленных
природой программирования для кластерных систем. Напомним, что в параллельной
программе над решением задачи работают одновременно несколько процессов, каждый
из которых, в свою очередь, может иметь несколько потоков команд. Это
обстоятельство существенно усложняет отладку, так как помимо ошибок, типичных
для последовательного программирования, появляются ошибки, совершаемые только
при разработке параллельных программ. К числу таких ошибок можно отнести,
например, сложно контролируемую ситуацию гонки процессов, когда процессы параллельной программы
взаимодействуют между собой без выполнения каких-либо синхронизирующих действий.
В этом случае, в зависимости от состояния вычислительной системы,
последовательность выполняемых действий может различаться от запуска к запуску
параллельной программы. Как результат, при наличии гонки процессов сложным
становится применение одного из основных принципов отладки – проверка
работоспособности при помощи тестов (однократное выполнение теста для
параллельной программы может не выявить ситуации гонки
процессов).
Однако инструменты и приемы, используемые в
Microsoft Visual Studio 2005 для отладки как последовательных, так и
параллельных программ, схожи, поэтому, если Вы имеете хороший опыт отладки
последовательных программ, то и отладка параллельных программ не покажется Вам
слишком сложной.
На практике познакомиться с процессом
отладки MPI программы можно в лабораторной работе «Отладка параллельных MPI
программ в среде Microsoft Visual Studio 2005
».
Обзор наиболее типичных ошибок при
написании MPI программ
Все ошибки, которые встречаются при последовательном программировании,
характерны также и для параллельного программирования. Однако кроме них есть ряд
специфических типов ошибок, обусловленных наличием в MPI задаче нескольких взаимодействующих
процессов. Дополнительные сложности в разработке параллельных программ
обуславливают повышенные требования к квалификации программистов, реализующих
параллельные версии алгоритмов. И хотя перечислить все типы ошибок, которые
могут возникнуть при программировании с использованием технологии MPI, крайне затруднительно,
дадим краткую характеристику ряду наиболее характерных ошибок, преследующих
начинающих разработчиков. К числу наиболее типичных ошибок при параллельном
программировании с использованием технологии MPI следует отнести:
- Взаимная блокировка при
пересылке сообщений. Предположим, что n процессов передают информацию друг
другу по цепочке так, что процесс с индексом i передает информацию процессу с
индексом i+1 (для индексов i=0,…,n-2), а процесс с индексом n-1 передает информацию процессу с
индексом 0. Передача
осуществляется с использованием функции отправки сообщений MPI_Send и функции приема сообщений MPI_Recv, при этом каждый процесс
сначала вызывает MPI_Send, а затем MPI_Recv. Функции являются
блокирующими, то есть MPI_Send возвратит управление только
тогда, когда передача будет завершена, или когда сообщение будет скопировано
во внутренний буфер. Таким образом, стандарт допускает возможность, что
функции отправки сообщения вернут управление только после того, как передача
будет завершена. Но передача не может завершиться, пока принимающий процесс не
вызовет функцию MPI_Recv. А функция MPI_Recv будет вызвана, в свою
очередь, только после того, как процесс завершит отправку своего сообщения.
Так как цепочка передачи сообщений замкнута, отправка сообщений может не
завершиться никогда, потому что каждый процесс будет ожидать завершения
отправки своего сообщения, и никто не вызовет функцию приема сообщения.
Избежать подобной блокировки можно, например, вызывая на процессах с четными
индексами сначала MPI_Send, а затем MPI_Recv, а на процессах с нечетными
индексами – в обратной порядке. Несмотря на очевидность ошибки, ее часто
допускают, так как при небольших сообщениях высока вероятность, что сообщения
уберутся во внутренние структуры библиотеки, функция отправки сообщения вернет
управление, и ошибка не даст о себе знать,

- Освобождение или изменение
буферов, используемых при неблокирующей пересылке. При
вызове неблокирующих функций возврат из них происходит немедленно, а адреса
массивов с сообщениями запоминаются во внутренних структурах библиотеки MPI.
При непосредственной передаче сообщений по сети, которая будет выполнена в
отдельном потоке, происходит обращение к исходному массиву с сообщением,
поэтому важно, чтобы этот участок памяти не был удален или изменен до
окончания передачи (установить, что передача завершена можно вызовом
специальных функций). Однако часто об этом правиле забывают, что приводит к
непредсказуемому поведению программы. Такого рода ошибки являются одними из
самых сложных для отладки,
- Несоответствие вызовов функций
передачи и приема сообщений. Важно следить, чтобы каждому вызову функции
отправки сообщения соответствовал вызов функции приема и наоборот. Однако в
том случае, когда число передач заранее не известно, а определяется в ходе
вычислений, бывает легко ошибиться и не обеспечить нужных гарантий выполнения
данного условия. К этому же типу ошибок можно отнести вызов функций передачи и
приема сообщений с несоответствующими тэгами идентификации сообщений.