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

Обрамляющие функции. Инициализация и завершение.

Самым первым вызовом MPI в любой программе, использующей эту библиотеку, должен быть вызов функции MPI_Init() – инициализация среды выполнения MPI.

#include <mpi.h>

int MPI_Init(int *argc, char ***argv);

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

Еще раз отметим, что функция MPI_Init() должна быть вызвана до любой другой функции MPI, кроме того, в любой программе она должна вызываться не более одного раза.

По завершении работы с MPI в каждой ветви необходимо вызвать функцию закрытия библиотеки – MPI_Finalize():

#include <mpi.h>

int MPI_Finalise(void);

После вызова этой функции невозможен вызов ни одной функции библиотеки MPI (в том числе и повторный вызов MPI_Init())

Для аварийного завершения работы с библиотекой MPI служит функция MPI_Abort().

#include <mpi.h>

int MPI_Abort(MPI_Comm comm, int errorcode);

Эта функция немедленно завершает все ветви приложения, входящие в коммуникационный контекст, который описывает коммуникатор comm. Код завершения приложения передается в параметре errorcode. Отметим, что MPI_Abort() вызывает завершения всех ветвей данного коммуникатора даже в том случае, если она была вызвана только в какой-либо одной ветви.

Синхронизация: барьеры.

Для непосредственной синхронизации ветвей в MPI предусмотрена одна специальная функция – MPI_Barrier().

#include <mpi.h>

int MPI_Barrier(MPI_Comm comm);

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

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

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

      1. Использование барьерной синхронизации.

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

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

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{

int size, rank, i;

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

MPI_Comm_size(MPI_COMM_WORLD, &size);

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

MPI_Comm_rank (MPI_COMM_WORLD, &rank);

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

/* задача с номером 0 сообщает пользователю размер группы,коммуникационный контекст которой описывает коммуникатор MPI_COMM_WORLD, т.е. число ветвей в приложении */

if (rank == 0) {

printf("Total processes count = %d\n", size );

}

/* Осуществляется барьерная синхронизация */

MPI_Barrier(MPI_COMM_WORLD);

/* Теперь каждая задача выводит на экран свой номер */

printf("Hello! My rank in MPI_COMM_WORLD = %d\n", rank);

/* Осуществляется барьерная синхронизация */

MPI_Barrier(MPI_COMM_WORLD);

/* затем ветвь c номером 0 печатает аргументы командной строки. */

if (rank == 0) {

printf(“Command line of process 0:\n");

for(i = 0; i < argc; i++) {

printf("%d: \"%s\"\n", i, argv[i]);

}

}

/* Все задачи завершают выполнение */

MPI_Finalize();

return 0;

}

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