Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Блокирующие коммуникационные операции




Синтаксис базовых коммуникационных функций MPI_Send и MPI_Recv был приведен в разделе 2, поэтому здесь мы рассмотрим только семантику этих операций.

В стандартном режиме выполнение операции обмена включает три этапа:

  1. Передающая сторона формирует пакет сообщения, в который помимо передаваемой информации упаковываются адрес отправителя (source), адрес получателя (dest), идентификатор сообщения (tag) и коммуникатор (comm). Этот пакет передается отправителем в системный буфер, и на этом функция посылки сообщения заканчивается.
  2. Сообщение системными средствами передается адресату.
  3. Принимающий процессор извлекает сообщение из системного буфера, когда у него появится потребность в этих данных. Содержательная часть сообщения помещается в адресное пространство принимающего процесса (параметр buf), а служебная - в параметр status.

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

  • коммуникатора (comm), поскольку каждый процесс может одновременно входить в несколько областей связи;
  • номера отправителя в этой области связи (source);
  • идентификатора сообщения (tag), который используется для взаимной привязки конкретной пары операций посылки и приема сообщений.

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

  • для идентификаторов сообщений (MPI_ANY_TAG - читать сообщение с любым идентификатором)
  • для адресов отправителя (MPI_ANY_SOURCE - читать сообщение от любого отправителя).

Не допускается расширенных запросов для коммуникаторов. Расширенные запросы возможны только в операциях чтения. Интересно отметить, что таким же образом организованы операции обмена в PSE nCUBE2 [1]. В этом отражается фундаментальное свойство механизма передачи сообщений: асимметрия операций передачи и приема сообщений, связанная с тем, что инициатива в организации обмена принадлежит передающей стороне.

Таким образом, после чтения сообщения некоторые параметры могут оказаться неизвестными, а именно: число считанных элементов, идентификатор сообщения и адрес отправителя. Эту информацию можно получить с помощью параметра status. Переменные status должны быть явно объявлены в MPI-программе. В языке C status - это структура типа MPI_Status с тремя полями MPI_SOURCE, MPI_TAG, MPI_ERROR. В языке FORTRAN status - массив типа INTEGER размера MPI_STATUS_SIZE. Константы MPI_SOURCE, MPI_TAG и MPI_ERROR определяют индексы элементов. Назначение полей переменной status представлено в таблице 3.2.

Таблица 3.2. Назначение полей переменной status.
Поля status C FORTRAN
Процесс-отправитель status.MPI_SOURCE status(MPI_SOURCE)
Идентификатор сообщения status.MPI_TAG status(MPI_TAG)
Код ошибки status.MPI_ERROR status(MPI_ERROR)

Как видно из таблицы 3.2, количество считанных элементов в переменную status не заносится.

Для определения числа фактически полученных элементов сообщения необходимо использовать специальную функцию MPI_Get_count:

C:

int MPI_Get_count (MPI_Status *status, MPI_Datatype datatype, int *count)

IN status - атрибуты принятого сообщения;
IN datatype - тип элементов принятого сообщения;
OUT count - число полученных элементов.

Подпрограмма MPI_Get_count может быть вызвана либо после чтения сообщения (функциями MPI_Recv, MPI_Irecv), либо после опроса факта поступления сообщения (функциями MPI_Probe, MPI_Iprobe). Операция чтения безвозвратно уничтожает информацию в буфере приема. При этом попытка считать сообщение с параметром count меньше, чем число элементов в буфере, приводит к потере сообщения.

Определить параметры полученного сообщения без его чтения можно с помощью функции MPI_Probe.

C:

int MPI_Probe (int source, int tag, MPI_Comm comm, MPI_Status *status)

IN source - номер процесса-отправителя;
IN tag - идентификатор сообщения;
IN comm - коммуникатор;
OUT status - атрибуты опрошенного сообщения.

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

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

CALL MPI_COMM_RANK(comm, rank, ierr)IF (rank.EQ.0) THEN CALL MPI_RECV(recvbuf, count, MPI_REAL, 1, tag, comm, status, ierr) CALL MPI_SEND(sendbuf, count, MPI_REAL, 1, tag, comm, ierr)ELSE IF (rank.EQ.1) THEN CALL MPI_RECV(recvbuf, count, MPI_REAL, 0, tag, comm, status, ierr) CALL MPI_SEND(sendbuf, count, MPI_REAL, 0, tag, comm, ierr)END IF

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

Приведем вариант правильной программы.

CALL MPI_COMM_RANK(comm, rank, ierr)IF (rank.EQ.0) THEN CALL MPI_SEND(sendbuf, count, MPI_REAL, 1, tag, comm, ierr) CALL MPI_RECV(recvbuf, count, MPI_REAL, 1, tag, comm, status, ierr)ELSE IF (rank.EQ.1) THEN CALL MPI_RECV(recvbuf, count, MPI_REAL, 0, tag, comm, status, ierr) CALL MPI_SEND(sendbuf, count, MPI_REAL, 0, tag, comm, ierr)END IF

Другие комбинации операций SEND/RECV могут работать или не работать в зависимости от реализации MPI (буферизованный обмен или нет).

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

С:

int MPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype,

int dest, int sendtag, void *recvbuf, int recvcount,

MPI_Datatype recvtype, int source, MPI_Datatypeа recvtag,

MPI_Comm comm, MPI_Status *status)

 

IN sendbuf - адрес начала расположения посылаемого сообщения;
IN sendcount - число посылаемых элементов;
IN sendtype - тип посылаемых элементов;
IN dest - номер процесса-получателя;
IN sendtag - идентификатор посылаемого сообщения;
OUT recvbuf - адрес начала расположения принимаемого сообщения;
IN recvcount - максимальное число принимаемых элементов;
IN recvtype - тип элементов принимаемого сообщения;
IN source - номер процесса-отправителя;
IN recvtag - идентификатор принимаемого сообщения;
IN comm - коммуникатор области связи;
OUT status - атрибуты принятого сообщения.

Функция MPI_Sendrecv совмещает выполнение операций передачи и приема. Обе операции используют один и тот же коммуникатор, но идентификаторы сообщений могут различаться. Расположение в адресном пространстве процесса принимаемых и передаваемых данных не должно пересекаться. Пересылаемые данные могут быть различного типа и иметь разную длину.

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

С:

MPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype,

int dest, int sendtag, int source, int recvtag,

MPI_Comm comm, MPI_Status *status)

INOUT buf - адрес начала расположения посылаемого и принимаемого сообщения;
IN count - число передаваемых элементов;
IN datatype - тип передаваемых элементов;
IN dest - номер процесса-получателя;
IN sendtag - идентификатор посылаемого сообщения;
IN source - номер процесса-отправителя;
IN recvtag - идентификатор принимаемого сообщения;
IN comm - коммуникатор области связи;
OUT status - атрибуты принятого сообщения.

В данной операции посылаемые данные из массива buf замещаются принимаемыми данными.

В качестве адресатов source и dest в операциях пересылки данных можно использовать специальный адрес MPI_PROC_NULL. Коммуникационные операции с таким адресом ничего не делают. Применение этого адреса бывает удобным вместо использования логических конструкций для анализа условий посылать/читать сообщение или нет. Этот прием будет использован нами далее в одном из примеров, а именно, в программе решения уравнения Лапласа методом Якоби.





Поделиться с друзьями:


Дата добавления: 2016-07-29; Мы поможем в написании ваших работ!; просмотров: 424 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Студент всегда отчаянный романтик! Хоть может сдать на двойку романтизм. © Эдуард А. Асадов
==> читать все изречения...

2395 - | 2153 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.012 с.