Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

PobedilRomanskogo / Введение в MPI

.pdf
Скачиваний:
20
Добавлен:
13.04.2015
Размер:
951.87 Кб
Скачать

Неблокирующий прием

call MPI_IRECV(buf, cnt, source, tag, comm, req, err)

Все аргументы аналогичны MPI_RECV. За исключением нового выходного аргумента req типа integer, идентификатора асинхронного приема данных.

Возврат из подпрограммы происходит сразу после инициализации процесса приема без ожидания получения сообщения в буфере buf.

21

Завершение асинхронного обмена

call MPI_WAIT(req, stat, err) - ожидание завершения асинхронных процедур MPI_ISEND или MPI_IRECV, ассоциированных с идентификатором req. В случае приема, атрибуты и длину полученного сообщения можно определить с помощью выходного массива stat (см. слайд №16).

call MPI_WAITALL(cnt, reqs, stats,err)

integer :: cnt ! Число операций приема или передачи integer, dimension(cnt) :: reqs ! Массив идентификаторов

integer,dimension(cnt,MPI_STATUS_SIZE) :: stats ! Массив статусов

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

ошибки в элементах массива stats будет установлено в

22

 

соответствующее значение.

integer :: stats(MPI_STATUS_SIZE,99) ! Не больше 100 процессов integer :: reqs(99), err, tag = 1, nreq, rk, sz

real :: arr(99)

………

if(rk == 0) then do i = 1, sz-1

! 0-ой процесс получает все данные

call MPI_IRECV(arr(i),1,MPI_REAL,i,MPI_ANY_TAG,MPI_COMM_WORLD,& reqs(i),err)

enddo

nreq = sz-1 ! число запросов else

! Все остальные шлют данные в 0-ой массив

call MPI_ISEND(arr(rk),1,MPI_REAL,0,tag,MPI_COMM_WORLD,reqs(1),err) nreq = 1 ! число запросов

endif

!Проводим какие-то вычисления, не зависящие от arr

…………

!Проверяем статус посылок и приемов

call MPI_WAITALL(nreq,reqs,stats,err)

………

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

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

Чтобы завершить неблокирующий обмен, используются MPI_WAIT / MPI_WAITALL (процедуры ожидания с блокировкой) или MPI_TEST / MPI_TESTALL (процедуры ожидания без блокировки).

Для определения структуры сообщения использовать: call MPI_IPROBE(source, tag, comm, flag, stat, err)

logical :: flag ! Выходной арг. показывает можно ли принять сообщение

Функции завершения обмена необходимы:

для правильной работы MPI,

для того, чтобы программист знал, что обмен завершен и можно использовать данные из буфера обмена.

24

Два в одном: объединенный обмен данными

call MPI_SENDRECV(sendbuf, sendcnt, sendtype, dest, sendtag, recvbuf, recvcnt, recvtype, source, recvtag, comm, stat, err)

sendbuf - буфера отправителя;

sendcnt - число элементов в буфере отправителя; sendtype - тип элементов в буфере отправителя; dest - номер процесса-получателя;

sendtag - тэг процесса-отправителя; recvbuf - приемный буфер (выходной арг.);

recvcnt - число элементов в приемном буфере; recvtype – тип элементов в приемном буфере; source - номер процесса-отправителя;

recvtag - тэг процесса-получателя; comm - коммуникатор;

stat - массива статус (выходной арг.) см. слайд №16.

MPI_SENDRECV - блокирующая передача и прием.

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

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

MPI_SENDRECV, то MPI сама разрешает такие ситуации.

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

26

call MPI_SENDRECV_REPLACE(buf, cnt, datatype, dest, sendtag, source, recvtag, comm, stat, err)

MPI_SENDRECV_REPLACE - блокирующая передача и прием. Один и тоже буфер buf используется для отправки и получения данных: посланное сообщение замещается полученным.

Принимаемое сообщение не должно превышать по размеру отправляемое сообщение, а передаваемые и принимаемые данные должны быть одного типа.

MPI_SENDRECV_REPLACE также гарантировано не вызывает блокировок.

27

Взаимоблокировки (deadlock)

Процесс 0

Процесс 1

 

 

RECV из процесса 1 RECV из процесса 0

SEND в процесс 1 SEND в процесс 0

При таком обмене гарантированно получим deadlock. Так как RECV не вернут управление, пока не получат данные.

MPI_SENDRECV и MPI_SENRECV_REPLACE делают программу более устойчивой, т.к. они берут на себя заботу о deadlock’ах.

Процесс 0

Процесс 1

 

 

RECV из процесса 1

IRECV из процесса 0

 

 

SEND в процесс 1

SEND в процесс 0

 

WAIT

 

 

IRECV

позволяет

избежать deadlock

28

Джокеры

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

Определены следующие джокеры: MPI_ANY_SOURCE – принимай от кого угодно (т.е. от любого процесса);

MPI_ANY_TAG – принимай, что угодно (т.е. с любым тэгом). MPI_PROC_NULL – несуществующий процесс.

Пользоваться джокерами следует с осторожностью,

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

использовать джокеры только в MPI_PROBE, MPI_IPROBE.

29

call MPI_COMM_SIZE(MPI_COMM_WORLD, sz, err) call MPI_COMM_RANK(MPI_COMM_WORLD, rk, err) nxt = rk+1

if(nxt == sz)nxt = MPI_PROC_NULL

call MPI_SEND(buf, 1, MPI_REAL, nxt,& tag, MPI_COMM_WORLD, err)

При вызове MPI_SEND с джокером MPI_PROC_NULL

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

Полезен при циклическом сдвиге процессов.

30

Соседние файлы в папке PobedilRomanskogo