Вперед: 4.3. Коммуникационные операции типа точка-точка
Назад: 4.1. Общая организация MPI
К содержанию: Оглавление


4.2. Базовые функции MPI

Любая MPI-программа должна начинаться с вызова функции инициализации MPI - функции MPI_Init. В результате выполнения этой функции создается область связи, описы┐ваемая предопределенным коммуникатором MPI_COMM_WORLD, в которую помещаются все запущенные процессы. Процессы упорядочены и пронумерованы от 0 до nproc-1, где nproc равно числу запущенных процессов. Кроме этого, создается предопределенный коммуникатор MPI_COMM_SELF, описывающий свою область связи для каждого отдельного процесса.

Вызов функции инициализации MPI_Init отличается в языках Cи и Fortran:

C:

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

Fortran:

MPI_INIT(IERROR)
INTEGER IERROR

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

Функция завершения MPI-программы MPI_Finalize

C:

int MPI_Finalize(void)

Fortran:

MPI_FINALIZE(IERROR)
INTEGER IERROR

Функция закрывает все MPI-процессы и ликвидирует все области связи.

Функция определения числа процессов в области связи MPI_Comm_size

C:

int MPI_Comm_size(MPI_Comm comm, int *size)

Fortran:

MPI_COMM_SIZE(COMM, SIZE, IERROR)
INTEGER COMM, SIZE, IERROR
IN comm
- коммуникатор;
OUT rank - номер процесса, вызвавшего функцию.

Функция возвращает номер процесса, вызвавшего эту функцию. Номера процессов лежат в диапазоне 0..size-1 (значение size может быть определено с помощью предыдущей функции). Подпрограмма является локальной.

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

Функция передачи сообщения MPI_Send

C:

int MPI_Send(void* buf, int count, MPI_Datatype datatype,int dest,int tag,MPI_Comm comm)

Fortran:

MPI_SEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM,IERROR)
<type> BUF(*)
INTEGER COUNT, DATATYPE, DEST, TAG, COMM, IERROR
IN buf
- адрес начала расположения пересылаемых данных;
IN count - число пересылаемых элементов;
IN datatype - тип посылаемых элементов;
IN dest - номер процесса-получателя в группе, связанной скоммуникатором comm;
IN tag - идентификатор сообщения;
IN comm - коммуникатор области связи.

Функция выполняет посылку count элементов типа datatype сообщения с идентификатором tag процессу dest в области связи коммуникатора comm. Переменная buf - это, как правило, массив или скалярная переменная. В последнем случае значение count = 1.

Функция приема сообщения MPI_Recv

C:

int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int source, int tag,MPI_Comm comm, MPI_Status *status)

Fortran:

MPI_RECV(BUF, COUNT, DATATYPE, SOURCE, TAG, COMM,STATUS, IERROR)
<type> BUF(*)
INTEGER COUNT, DATATYPE, SOURCE, TAG, COMM,STATUS(MPI_STATUS_SIZE), IERROR
OUT buf
- адрес начала расположения принимаемого сообщения;
IN count - максимальное число принимаемых элементов;
IN datatype - тип элементов принимаемого сообщения;
IN source - номер процесса-отправителя;
IN tag - идентификатор сообщения;
IN comm - коммуникатор области связи;
OUT status - атрибуты принятого сообщения.

Функция выполняет прием count элементов типа datatype сообщения с идентификатором tag от процесса source в области связи коммуникатора comm.

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

Функция отсчета времени (таймер) MPI_Wtime

C:

double MPI_Wtime(void)

Fortran:

DOUBLE PRECISION MPI_WTIME().

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

{
double starttime, endtime;
starttime = MPI_Wtime();
: хронометрируемый участок :
endtime = MPI_Wtime();
printf("Выполнение заняло %f секунд\n",endtime-starttime);
}

Функция MPI_Wtick, имеющая точно такой же синтаксис, возвращает разрешение таймера (минимальное значение кванта времени).

Приведем примеры простейших MPI-программ

Программа simple.c

#include "mpi.h"
#include <stdio.h>

 int main(argc,argv)
 int argc;
 char *argv[]; {
 int numtasks, rank, rc; 

 MPI_Init(&argc,&argv);

 MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
 MPI_Comm_rank(MPI_COMM_WORLD,&rank);
 printf ("Number of tasks= %d My rank= %d\n", numtasks,rank);
 MPI_Finalize();
 }

Программа simple.f

program simple
 include 'mpif.h'

 integer numtasks, rank, ierr, rc

 call MPI_INIT(ierr)

 call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
 call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr)
 print *, 'Number of tasks=',numtasks,' My rank=',rank
 call MPI_FINALIZE(ierr)
 end


Вперед: 4.3. Коммуникационные операции типа точка-точка
Назад: 4.1. Общая организация MPI
К содержанию: Оглавление