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

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


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


Содержание

  1. Обзор
  2. Основной тупик
  3. Определение информации о сообщении
  4. Специальные параметры
  5. Реализация MPICH
  6. Рекомендации по программированию

Литература


1. Обзор

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

Тупик

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

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

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

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

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

Джокеры - MPI_ANY_SOURCE и MPI_ANY_TAG

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

Пустые Процессы и Запросы

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


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

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

На следующей диаграмме представлены две задачи типа 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

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


3.2 Статус (Status)

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

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


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


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

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


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

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

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

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

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

Проверь значения полей "статуса (status)" для сообщения проблемы.

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

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

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

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

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


Литература

Cornell Theory Center MPI Point to Point Communication I

Богачёв К.Ю. Основы параллельного программирования. -- М.: БИНОМ. Лаборатория знаний, 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 руководство.