Презентацию к данной лекции Вы можете скачать здесь.
Двухточечный (point-to-point, p2p) обмен
В двухточечном обмене участвуют только два процесса, процесс-отправитель и процесс-получатель (источник сообщения и адресат). Двухточечные обмены используются для организации локальных и неструктурированных коммуникаций.
Имеется несколько разновидностей двухточечного обмена
Двухточечный обмен возможен только между процессами, принадлежащими одной области взаимодействия (одному коммуникатору).
Правильно организованный двухточечный обмен сообщениями должен исключать возможность блокировки или некорректной работы параллельной MPI-программы.
Примеры ошибок в организации двухточечных обменов:
Правильно
Неправильно
Неправильно
В MPI приняты следующие соглашения об именах подпрограмм двухточечного обмена:
MPI_[I][R, S, B]Send
здесь префикс [I] (Immediate) обозначает неблокирующий режим. Один из префиксов [R, S, B] обозначает режим обмена: по готовности, синхронный и буферизованный.
Отсутствие префикса обозначает подпрограмму стандартного обмена.
Имеется 8 разновидностей операции передачи сообщений.
Для подпрограмм приема:
MPI_[I]Recv
то есть всего 2 разновидности приема.
Подпрограмма приема любого типа может принять сообщения от любой подпрограммы передачи.
Передача-прием сообщения (p2p)
Cтандартная блокирующая передача
MPI_Recv(buf, count, datatype, dest, tag, comm, status, ierr)
MPI_Send(buf, count, datatype, dest, tag, comm, ierr)
buf - адрес первого элемента в буфере передачи;count - количество элементов в буфере передачи (допускается count = 0);datatype - тип MPI каждого пересылаемого элемента;dest - ранг процесса-получателя сообщения (целое число от 0 до n – 1, где
n число процессов в области взаимодействия);tag - тег сообщения;comm - коммуникатор;ierr - код завершения.При стандартной блокирующей передаче после завершения вызова (после возврата из функции/процедуры передачи) можно использовать любые переменные, использовавшиеся в списке параметров. Такое использование не повлияет на корректность обмена.
Дальнейшая "судьба" сообщения зависит от реализации MPI. Сообщение может быть сразу передано процессу-получателю или может быть скопировано в буфер передачи.
Завершение вызова не гарантирует доставки сообщения по назначению. Такая гарантия предоставляется при использовании других разновидностей двухточечного обмена (см. далее материал этой лекции).
Cтандартный блокирующий прием
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
MPI_Recv(buf, count, datatype, dest, tag, comm, status, ierr)
buf - адрес первого элемента в буфере передачи;count - количество элементов в буфере передачи;datatype - тип MPI каждого пересылаемого элемента;source - ранг процесса-отправителя сообщения ( целое число от 0 до n – 1, где n число процессов в области взаимодействия);tag - тег сообщения;comm - коммуникатор;status - статус обмена;ierr - код завершения.Значение параметра count может оказаться больше, чем количество элементов в принятом сообщении. В этом случае после выполнения приема в буфере изменится значение только тех элементов, которые соответствуют элементам фактически принятого сообщения.
Для функцииMPI_Recv гарантируется, что после завершения вызова сообщение принято и размещено в буфере приема.
Джокеры
В качестве ранга источника сообщения и в качестве тега сообщения можно использовать "джокеры" :
Подпрограмма MPI_Recv может принимать сообщения, отправленные в любом режиме.
Прием может выполняться от произвольного процесса, а в операции передачи должен быть указан вполне определенный адрес. Приемник может использовать джокеры для источника и для тега. Процесс может отправить сообщение и самому себе, но следует учитывать, что использование в этом случае блокирующих операций может привести к "тупику".
Пример использования операции блокирующего двухточечного обмена
#include <mpi.h>
#include <stdio.h>
int main ( int argc, char *argv[] ) {
int ProcNum, ProcRank, tmp;
MPI_Status status;
MPI_Init ( argc, argv );
MPI_Comm_size ( MPI_COMM_WORLD, ProcNum);
MPI_Comm_rank ( MPI_COMM_WORLD, ProcRank);
if(ProcRank == 0){
printf("Hello world from process %i \n", ProcRank);
for(int i = 1; i < ProcNum; i++){
MPI_Recv(tmp,1,MPI_INT,MPI_ANY_SOURCE,0,MPI_COMM_WORLD, status);
printf("Hello world from process %i \n", tmp);
}
}else{
MPI_Send(ProcRank,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
Размер полученного сообщения (count) можно определить с помощью вызова подпрограммы
int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count)
MPI_Get_count(status, datatype, count, ierr)
count - количество элементов в буфере передачи;datatype - тип MPI каждого пересылаемого элемента;status - статус обмена;ierr - код завершения.Аргумент datatype должен соответствовать типу данных, указанному в операции обмена
Передача сообщения в буферизованном режиме может быть начата независимо от того, зарегистрирован ли соответствующий прием. Источник копирует сообщение в буфер, а затем передает его в неблокирующем режиме.
Размер буфера должен превосходить размер сообщения на величину 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;}
Завершение передачи происходит только после того, как прием сообщения инициализирован другим процессом. Адресат посылает источнику "квитанцию" - уведомление о завершении приема. После получения этого уведомления обмен считается завершенным и источник "знает", что его сообщение получено:
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)
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.