Двухточечные обмены
Стандартный блокирующий двухточечный обмен
Передача-прием сообщения (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_ANY_SOURCE - любой источник;
- MPI_ANY_TAG - любой тег.
Подпрограмма 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 должен соответствовать типу данных, указанному в операции обмена