Вычислительный центр им. А.А. Дородницына РАН    

Раздел виртуального курса
Параллельное программирование в интерфейсе MPI


MPI попарный обмен сообщениями II


Содержание

1.     Обзор

2.     Основной тупик

3.     Определение информации о сообщении

3.1 Wait, Test и Probe
3.2
Status

4.     Специальные параметры

5.     Реализация MPICH

6.     Рекомендации по программированию

Литература


1. Обзор

Начнем с обзора вариантов программирования, описанных в данном модуле.

Тупик

Ситуация тупика (deadlock) часто встречается в параллельной обработке. Эта ситуация возникает, когда два или больше процессов соревнуются за один и тот же набор ресурсов. В типичном сценарии в коммуникацию вовлечены два процесса, желающих обменяться сообщениями, причем оба пытаются отдать их противоположному процессу, хотя ни один еще не готов принять сообщение. Здесь описан ряд стратегий, помогающих избежать такого рода проблемы, встречающиеся в приложениях.

Проверка и исполнение по "состоянию" коммуникаций

При вовлечении в неблокирующие транзакции (пересылки) вызов функций wait (ожидание), test (проверка) и probe (зондирование) позволяют приложению запросить статус (status) отдельных сообщений или проверить любое сообщение, обладающее определенным набором характеристик, без извлечения любой завершенной транзакции из очереди.

Проверка статуса, возвращаемого из транзакции, позволяет приложению произвести, например, корректирующие действия в случае, если возникла ошибка.

Использование специальных параметров для специальных случаев

Джокеры - MPI_ANY_SOURCE и MPI_ANY_TAG

Использование вызовов с джокерами позволяет получающему процессу конкретизировать получаемое сообщение, при этом джокер используется для указания либо отправителя, либо типа сообщения.

Пустые (Null) процессы и запросы

Специальные пустые параметры могут упростить кодирование приложений, делая структуры данных регулярными.


2. Основной тупик

Явление тупика (deadlock) наиболее распространено при блокирующих коммуникациях. Тупик возникает, когда все задачи ожидают событий, которые еще не были инициализированы.

На следующей диаграмме представлены две задачи типа SPMD (единственная программа/многокомпонентные данные): обе вызывают блокирующие стандартные отправки в той же точке программы. Спаренное с отправкой получение у каждой задачи происходит позже в другой программе этой задачи.

Простейший пример тупика: каждая отправка из двух ждет соответствующего ей получения, чтобы завершиться, но эти получения исполняются после отправок, так что если отправки не завершены и не вернулись, то получения никогда не смогут исполниться и оба набора коммуникаций ⌠подвиснут■ на неопредел╦нное время.

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

Исключение тупиков:

Есть четыре способа избежать тупика:

1.     различный порядок вызовов у задач

Можно определить порядок, в котором одна задача объявляет первой свое получение, а вторая объявляет первой свою отправку. Согласно этому порядку сообщение в одном из направлений приходит раньше, чем в другом.

2.     неблокирующие вызовы

Неблокирующие вызовы заставляют каждую задачу объявить неблокирующее получение до того, как она произведет какую-нибудь другую коммуникацию. Это позволяет получить все сообщения независимо от момента прибытия сообщения, порядка, в котором отправки объявлены и тех действий, которые задача выполняет.

3.    MPI_Sendrecv
MPI_Sendrecv_replace

Функция MPI_Sendrecv √ это элегантное решение, использующее возможности самой библиотеки MPI для исключения тупика. В этой версии используется два буфера: один для отправляемого сообщения, а другой для получаемого. В версии replace система выделяет некоторое единственное буферное пространство (не зависящее от порогового предела) для обработки обмена сообщениями. Отправленное сообщение в этом буфере замещается полученным сообщением.

Заметим здесь, что обмен с процессом, который имеет пустое значение MPI_PROC_NULL, не дает результата, а отправка на пустой процесс MPI_PROC_NULL срабатывает.

4.     буферизованный способ

Также можно использовать буферизованную отправку, чтобы осуществлять вычисления после копирования отправляемого сообщения в пользовательский буфер. Это дает возможность исполнения получений. Буферизованные отправки обсуждались ранее в модуле попарный обмен сообщениями I.


3. Определение информации о сообщении

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

3.1 Wait, Test и Probe

Даже при условии правильно разделенных коммуникаций в соответствии с основным направлением вычислений, необходимо уметь не только получать информацию о статусе коммуникационной транзакции, но и организовывать будущие действия в зависимости от полученной информации. В дальнейшем будет описано три вызова, которые наиболее полезны для выполнения этих задач.

      MPI_Wait

o     Вызов полезен для обоих участников неблокирующей коммуникации: отправителя и получателя

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

o      Получающий процесс блокируется до тех пор, пока сообщение принимается

Со стороны получателя процесс уже объявил неблокирующее получение, которое будет завершено независимо от действий вызывающего процесса. Поэтому программист способен определить, совершено или нет какое-либо полезное вычисление перед тем, как запрашивается информация из еще не полученного сообщения. Если в наличии есть полезная работа, до момента принятия сообщения эффективность работы приложения будет существенно повышена, поскольку приложение будет выполнять эту работу. В какой-то момент, естественно, понадобится сообщение, тогда вызов ожидания (wait) и будет использован.

o      Отправляющий процесс заблокирован до тех пор, пока операция отправки не завершится. К этому времени буфер сообщения можно снова использовать

Со стороны отправки процесс также освобождается от транзакции. Единственно, процесс не должен делать что-то еще, кроме записи чего-либо в буфер до тех пор, пока его текущее использование не завершится. Если отправитель пытается сохранить некоторое другое сообщение в этот буфер до того, как предшествующая пересылка завершится, результаты не будут определены, а будут основаны исключительно на том, какая часть процесса была в обработке, когда произошла перезапись. Осуществление вызова wait на сообщение гарантирует, что повторное использование буфера не приведет к отрицательным последствиям.

      MPI_Test

o      Используется обоими участниками неблокирующей коммуникации: отправителем и получателем

Если wait задерживает исполнение до тех пор, пока операция не завершится, то test немедленно возвращает информацию о текущем состоянии операции.

o    Получатель проверяет, что определенный отправитель отослал сообщение, которое ожидает свою передачу. При этом сообщения от всех других отправителей игнорируются

Вызов test возвратит значение true только в том случае, если указанный пользователь отослал сообщение, которое в данный момент находится в очереди на отправку. Поток сообщений от всех прочих источников игнорируется.

o      Отправитель может выяснить, возможно ли использовать заново буфер сообщения. При этом, до того, как использовать буфер заново, необходимо подождать, пока операция не завершится

На стороне отправителя test является неблокирующим аналогом wait. Test предоставляет приложению информацию о текущем состоянии без требования блокировки приложения до завершения его работы. Это позволяет приложению выполнять другое задание, если что-либо имеется в наличии.

      MPI_Probe

o      Получатель извещается в том случае, когда сообщения от потенциально любого отправителя прибывают и готовы к выполнению (т.е., это блокирующий вызов).

Для всех предыдущих вызовов определены конкретные сообщения и отправители. Вызов probe может быть использован для возврата информации о доставке, касающейся как любого отправителя, так и некоторого конкретного отправителя.


3.2 Статус (Status)

o       статус возвращает источник, тег и ошибку (в стандартном случае)

Статус - это объект, который содержит информацию об источнике и теге сообщения, а также о любой ошибке, которую может иметь коммуникационный вызов. В языке программирования C статус возвращаются как status.MPI_SOURCE, status.MPI_TAG и status.MPI_ERROR. В случае отправок, информация о статусе, скорее всего, не отличается от той, которая была в вызове, поэтому она используется довольно редко.

o        MPI_Get_count возвращает количество элементов

Данный вызов может быть полезен, если вы распределили буфер получателя, который может быть больше, чем входящее сообщение. Так же с помощью этого вызова можно узнать длину сообщения, идентифицированного с помощью MPI_Probe.

o       Условия, в которых имеет смысл проверять статус

Информация, которую представляет статус, оказывается крайне полезной, когда используются следующие вызовы. Эти случаи не будут обсуждаться за исключением вызовов MPI_ANY_TAG и MPI_ANY_SOURCE, которые в дальнейшем будут кратко описаны.

 

      блокирующее получение или ожидание, когда должны быть использованы MPI_ANY_TAG или MPI_ANY_SOURCE

        MPI_ANY_TAG √ принимает сообщение с любым значение тега

        MPI_ANY_SOURCE √ принимает сообщение от любого источника

 

         MPI_Probe или MPI_Iprobe √ получения информации по приходящим сообщениям

       MPI_Probe √ блокирующий тест для некоторого сообщения

       MPI_Iprobe √ неблокирующий тест для некоторого сообщения

         MPI_Test служит для того, чтобы узнать, завершена ли коммуникация


4. Специальные параметры

o       Джокеры (wildcard) - MPI_ANY_SOURCE и MPI_ANY_TAG

Родовой термин, имеющий значение "что-либо, отвечающее очень общему множеству характеристик". MPI_ANY_SOURCE позволяет получателю получить сообщения от любого отправителя, а MPI_ANY_TAG позволяет получателю получить любой тип сообщения от отправителя.

o       Пустые (nullv) процессы и запросы

Приложения часто имеют дело с регулярными структурами данных, такими как прямоугольные гипер-массивы, и выполняют один и тот же тип коммуникаций внутри этих структур данных за исключением краев, для которых приходится писать специальный код, чтобы не осуществлять коммуникации там, где нет годных для этого "соседей" для отправки или получения. В таком случае применяются специальные пустые параметры, которые существенно упрощают создание приложений.

 


5. Реализация MPICH

В реализации MPICH стандартный, синхронный и буферизованный способы коммуникации работают согласно стандарту.


6. Рекомендации по программированию

o      Избегайте тупика посредством продуманного размещения вызовов отправок/получений или ранним объявлением неблокирующих получений

Если вы выбрали использование блокирующих транзакций, попытайтесь обеспечить исключение тупика посредством тщательной разработки вашей коммуникационной стратегии. Для этого отправки и получения должны быть надлежащим образом спарены в необходимом порядке. Также, можно объявить неблокирующее получения настолько рано, насколько это возможно. В таком случае отправки будут простаивать в системе настолько мало времени, насколько это необходимо.

o      Используйте вызов "состояния операции" ("wait", "test" или "probe"), чтобы контролировать функционирование вызовов неблокирующих коммуникаций

Знание о состоянии коммуникационных транзакций позволяет приложению продуманно управляться с работой, улучшая эффективность использования имеющихся циклов. В конце концов, ⌠подвешенный■ обмен должен сработать, но такое действие может занять слишком много времени, причем многие транзакции, возможно, могут быть выполнены не до конца. Вызовы wait, test и probe позволяют приложению скоординировать свою работу с положением дел в системе.

o      Проверяйте значения полей статуса (status) для вывода информации о проблеме

Нельзя априори предполагать, что программа сработает √ необходимо сделать общим правилом проверку на пригодность любой транзакции. Также нужно, чтобы сообщения о фатальных ошибках и любая, относящаяся к делу информация, немедленно поступала пользователю.

o      Продуманное использование джокеров может значительно упростить логику и кодирование

Используя общие параметры, получения способны обработать более чем один тип потока сообщений (в терминах либо отправителя, либо типа сообщения, либо обоих), что может значительно упростить структуру вашего приложения и позволить сэкономить на системных ресурсах (в случае, если используется уникальный буфер сообщения для каждой транзакции).

o       Пустые (фиктивные) процессы и запросы перемещают тесты из пользовательского кода

Использование MPI_PROC_NULL и MPI_REQUEST_NULL освобождает от граничных испытаний и позволяет программисту использовать вызов, который будет проигнорирован системой.

 


Литература

Cornell Theory Center MPI Point to Point Communication II

Богач╦в К.Ю. Основы параллельного программирования. -- М.: БИНОМ. Лаборатория знаний, 2003. -- 342 с.

Немнюгин С.А., Стесик О.Л. Параллельное программирование для многопроцессорных вычислительных систем. -- СПб.: БХВ-Петербург, 2002. -- 400 с.: ил.

MPI Home Page at Argonne National Labs http://www.mcs.anl.gov/mpi

Message Passing Interface Forum (1995) MPI: A Message Passing Interface Standard. June 12, 1995. Доступен на русском языке в pdf-формате из сайта http://www.cluster.bsu.by/MPI_ALL.htm


[Quiz]Вопросы для проверки усвоения материала

[Exercise]Лабораторная работа


 

 

╘ 2003 Вычислительныйцентр им. А.А.Дородницына Все права защищены.
Прочтите наше Copyright руководство.