Санкт-Петербургский государственный университет
Опубликован: 11.10.2012 | Доступ: свободный | Студентов: 955 / 173 | Длительность: 05:14:00
Лекция 3:

Двухточечные обмены

< Лекция 2 || Лекция 3: 123 || Лекция 4 >

Двухточечный обмен с буферизацией

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

Размер буфера должен превосходить размер сообщения на величину MPI_BSEND_OVERHEAD. Это дополнительное пространство используется подпрограммой буферизованной передачи для своих целей.

Если перед выполнением операции буферизованного обмена не выделен буфер, MPI ведет себя так, как если бы с процессом был связан буфер нулевого размера. Работа с таким буфером обычно завершается сбоем программы.

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

При выполнении буферизованного обмена программист должен заранее создать буфер достаточного размера:

                        
int MPI_Buffer_attach(void *buf, size)

MPI_Buffer_attach(buf, size, ierr)
           

В результате вызова создается буфер buf размером size байтов. В программах на языке Fortran роль буфера может играть массив. За один раз к процессу может быть подключен только один буфер.

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

                        
int MPI_Bsend(void *buf, int count, MPI_Datatype datatype, int   dest, int tag, MPI_Comm comm)

MPI_Bsend(buf, count, datatype, dest, tag, comm, ierr)
           

После завершения работы с буфером его необходимо отключить:

                        
int MPI_Buffer_detach(void *buf, int *size)

MPI_Buffer_detach(buf, size, ierr)
           

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

Пример программы, использующей обмен с буферизацией

                        
#include "mpi.h"
#include <stdio.h>
int main(int argc,char *argv[])
{
 int *buffer;
 int myrank;
 MPI_Status status;
 int buffsize = 1;
 int TAG = 0;
 MPI_Init(&argc, &argv);
 MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
 if (myrank == 0)
{
 buffer = (int *) malloc(buffsize + MPI_BSEND_OVERHEAD);
 MPI_Buffer_attach(buffer, buffsize + MPI_BSEND_OVERHEAD);
 buffer = (int *) 10;
 MPI_Bsend(&buffer, buffsize, MPI_INT, 1, TAG, MPI_COMM_WORLD);
 MPI_Buffer_detach(&buffer, &buffsize);
}
else
{
 MPI_Recv(&buffer, buffsize, MPI_INT, 0, TAG, MPI_COMM_WORLD, &status);
 printf("received: %i\n", buffer);
}
 MPI_Finalize();
 return 0;} 
             

Другие разновидности двухточечного обмена

Cинхронный обмен

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

                                    
int MPI_Ssend(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

MPI_SSEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERR)
                

Обмен "по готовности"

Передача "по готовности" выполняется с помощью подпрограммы MPI_Rsend:

                                    
int MPI_Rsend(void *buf, int count, MPI_Datatype  datatype, int dest, int tag, MPI_Comm comm)
 
MPI_Rsend(buf, count, datatype, dest, tag, comm, ierr)

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

Совместные прием и передача

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

Подпрограммы приемопередачи могут взаимодействовать с обычными подпрограммами обмена и подпрограммами зондирования.

Подпрограмма 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, int recvtag, MPI_Comm comm, MPI_Status *status)

MPI_Sendrecv(sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm, status, ierr) 
                    

Имеются разновидности операции приемопередачи.

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

                        
int MPI_Sendrecv_replace(void *buf, int count,  MPI_Datatype datatype, int dest, int sendtag, 
int source,  int recvtag, MPI_Comm comm, MPI_Status *status)

MPI_Sendrecv_replace(BUF, COUNT, DATATYPE, DEST, SENDTAG, SOURCE, RECVTAG, COMM, STATUS, IERR) 
                    
< Лекция 2 || Лекция 3: 123 || Лекция 4 >