Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Processes - Metodicka (edited) with MPI - last....doc
Скачиваний:
78
Добавлен:
22.12.2018
Размер:
1.59 Mб
Скачать
      1. Mpi: коммуникации «точка-точка». «Пинг-понг».

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

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{

int size, rank, max, i = 1, j, prev, next;

MPI_Request recv_request, send_request;

MPI_Status status;

MPI_Init(&argc, &argv); /* Инициализируем библиотеку */

MPI_Comm_size(MPI_COMM_WORLD, &size);

/* Узнаем количество задач в запущенном приложении... */

MPI_Comm_rank (MPI_COMM_WORLD, &rank);

/* ...и свой собственный номер: от 0 до (size-1) */

/* определяем максимум */

if ((argc < 2) || ((max = atoi(argv[1])) <= 0)) {

printf("Bad arguments!\n");

MPI_Finalize();

return 1;

}

/* каждая ветвь определяет, кому посылать и от кого принимать сообщения */

next = (rank + 1) % size;

prev = (rank == 0) ? (size - 1) : (rank - 1);

if (rank == 0) {

/* ветвь с номером 0 начинает «пинг-понг» */

MPI_Isend(&i, 1, MPI_INT, 1, next, MPI_COMM_WORLD, &send_request);

printf("process %d sent value \"%d\" to process %d\n", rank, i, next);

MPI_Wait(&send_request, NULL);

}

while ((i > 0) && (i < max)) {

MPI_Irecv(&i, 1, MPI_INT, prev, MPI_ANY_TAG, MPI_COMM_WORLD, &recv_request);

MPI_Wait(&recv_request, &status);

if (i > 0) {

printf("process %d received value \"%d\" " + "from process %d\n", rank, i++, prev);

if (i == max) {

i = 0;

}

MPI_Isend(&i, 1, MPI_INT, next, 0, MPI_COMM_WORLD, &send_request);

printf("process %d sent value \"%d\" " + " to process %d\n", rank, i, next);

MPI_Wait(&send_request, NULL);

} else if (i == 0) {

MPI_Isend(&i, 1, MPI_INT, next, 0, MPI_COMM_WORLD, &send_request);

MPI_Wait(&send_request, NULL);

break;

}

}

MPI_Finalize();

return 0;

}

      1. Коллективные коммуникации.

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

Отметим, что хотя все те же самые действия можно запрограммировать с использованием коммуникаций «точка-точка», однако более целесообразным является применение коллективных функций, и тому есть несколько причин. Во-первых, во многих случаях использование коллективной функции может быть эффективнее, нежели моделирование ее поведения при помощи функций обмена «точка-точка», так как реализация коллективных функций может содержать некоторую оптимизацию (например, при рассылке всем ветвям одинаковых данных может использоваться не последовательная посылка всем ветвям сообщений от одной выделенной ветви, а распространение сообщения между ветвями по принципу двоичного дерева). Кроме того, при использовании коллективных функций сводится к нулю риск программной ошибки, связанной с тем, что сообщение из коллективного потока данных будет перепутано с другим, индивидуальным сообщением (например, получено вместо него при использовании констант MPI_ANY_SOURCE, MPI_ANY_TAG в качестве параметров функции приема сообщения). При передаче сообщений, формируемых коллективными функциями, используется временный дубликат заданного коммуникатора, который неявно создается библиотекой на время выполнения данной функции и уничтожается автоматически после ее завершения. Таким образом, сообщения, переданные коллективной функцией, могут быть получены в других или в той же самой ветви только при помощи той же самой коллективной функции.

Важной особенностью любой коллективной функции является то, что ее поведение будет корректным только в том случае, если она была вызвана во всех ветвях, входящих в заданный коммуникационный контекст. В некоторых (или во всех) ветвях при помощи этой функции данные будут приниматься, в некоторых (или во всех) ветвях – отсылаться. Иногда с помощью одного вызова происходит одновременно и отправка, и прием данных. Как правило, все ветви должны вызвать коллективную функцию с одними и теми же значениями фактических параметров (за исключением параметров, содержащих адреса буферов – эти значения, разумеется, в каждой ветви могут быть своими). Все коллективные функции имеют параметр-коммуникатор, описывающий коммуникационный контекст, в котором происходит коллективный обмен.

Семантика буферизации для коллективных функций аналогична стандартному режиму буферизации для одиночных коммуникаций в блокирующем режиме: возврат управления из коллективной функции означает, что вызвавшая ветвь может повторно использовать буфер, в котором содержались данные для отправки (либо гарантирует, что в буфере для приема находятся принятые данные). При этом, отнюдь не гарантируется, что в остальных ветвях к этому моменту данная коллективная операция также завершилась (и даже не гарантируется, что она в них уже началась). Таким образом, хотя в некоторых случаях возврат из коллективных функций действительно происходит во всех ветвях одновременно, нельзя полагаться на этот факт и использовать его для целей синхронизации ветвей. Для явной синхронизации ветвей может использоваться лишь одна специально предназначенная коллективная функция – это описанная выше функция MPI_Barrier().

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]