Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие по MPI (реферат).doc
Скачиваний:
61
Добавлен:
28.06.2014
Размер:
124.42 Кб
Скачать

-----------------------------------------------------------------------------------------------------------------

3. Разрешение взаимной блокировки Send/Recv с помощью функции mpi_Sendrecv

Пример взаимной блокировки этих двух функций:

Допустим, у нас есть несколько процессов, которые взаимодействуют следующим образом:

Каждый процесс содержит следующий код:

for(i=0; i<n; i++)

{

MPI_Send(…);

}

for(i=0; i<n; i++)

{

MPI_Recv(…);

}

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

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

int MPI_Sendrecv(void *sbuf, int scount, MPI_Datatype stype, int dest, int stag, void *rbuf, int count, MPI_Datatype rtype, int source, int rtag, MPI_Comm comm, MPI_Status *status), где

  • sbuf, scount, stype, dest, stag — параметры передаваемого сообщения;

  • rbuf, rcount, rtype, source, rtag — параметры принимаемого сообщения;

  • comm — коммуникатор, в рамках которого выполняется передача данных;

  • status — структура данных с информацией о результате выполнения операции.

Тогда каждый процесс будет содержать следующий код:

for(i=0; i<n; i++)

{

MPI_Sendrecv(…);

}

------------------------------------------------------------------------

4. Пример использования mpi_Waitall, mpi_Waitany

Процедура MPI_Waitall:

int MPI_Waitall(int count, MPI_Request *requests, MPI_Status *statuses), где

–      count - число идентификаторов;

–      requests - массив идентификаторов асинхронного приема или передачи;

–      OUT statuses - параметры сообщений.

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

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

# include <mpi.h>

# include <stdio.h>

int main(int argc, char** argv)

{

int numtasks, rank, next, prev, buf[2], tag1 = 1, tag2 = 2;

MPI_Request reqs[4];

MPI_Status stats[4];

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

prev = rank - 1;

next = rank + 1;

if (rank == 0) prev = numtasks - 1;

if (rank == (numtasks - 1)) next = 0;

MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]);

MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]);

MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD, &reqs[2]);

MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD, &reqs[3]);

MPI_Waitall(4, reqs, stats);

printf("Node %d: all ok!\n", rank);

MPI_Finalize();

}

Результат выполнения программы на 4 процессах:

Node 1: all ok!

Node 3: all ok!

Node 2: all ok!

Node 0: all ok!

Процедура MPI_Waitany:

int MPI_Waitany(int count, MPI_Request *requests, int *index, MPI_Status *status), где

–      count - число идентификаторов;

–      requests - массив идентификаторов асинхронного приема или передачи;

–      OUT index - номер завершенной операции обмена;

–      OUT status - параметры сообщений.

Выполнение процесса блокируется до тех пор, пока какая-либо операция обмена, ассоциированная с указанными идентификаторами, не будет завершена. Если несколько операций могут быть завершены, то случайным образом выбирается одна из них. Параметр index содержит номер элемента в массиве requests, содержащего идентификатор завершенной операции.

Пример. Изменим предыдущий пример используя функциюMPI_WaitanyвместоMPI_Waitall.

# include <mpi.h>

# include <stdio.h>

int main(int argc, char** argv)

{

int numtasks, rank, next, prev, buf[2], tag1 = 1, tag2 = 2;

int *i;

MPI_Request reqs[4];

MPI_Status stats[4];

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

prev = rank - 1;

next = rank + 1;

if (rank == 0) prev = numtasks - 1;

if (rank == (numtasks - 1)) next = 0;

MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]);

MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]);

MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD, &reqs[2]);

MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD, &reqs[3]);

MPI_Waitany(4, reqs, &i, stats);

printf("Node %d: all ok!\n", rank);

MPI_Finalize();

}

Результат выполнения программы на 4 процессах:

Node 1: all ok!

Node 3: all ok!

Node 2: all ok!

Node 0: all ok!