Программирование с использованием Intel MPI. Введение
Привязки к языкам программирования
Привязка к языку C
При использовании MPI в программах на языке C в именах функций используется префикс MPI_, а первая буква имени набирается в верхнем регистре.
Согласно спецификации имена подпрограмм имеют вид Класс_действие_подмножество или Класс_действие. Аналогичное правило действует и для подпрограмм MPI для языка Fortran. В C++ подпрограмма является методом для определенного класса, имя имеет в этом случае вид MPI::Класс::действие_подмножество.
Для некоторых действий введены стандартные наименования:
- Create - создание нового объекта;
- Get - получение информации об объекте;
- Set - установка параметров объекта;
- Delete - удаление информации;
- Is - запрос о том, имеет ли объект указанное свойство.
Значения кода завершения имеют целый тип и определяются по значению функции. Имена констант MPI записываются в верхнем регистре. Их описания находятся в заголовочном файле mpi.h, который обязательно включается в MPI-программу. Имя этого файла может быть другим в других реализациях MPI. Входные параметры функций передаются по значению, а выходные (и INOUT) — по ссылке.
В MPI принята своя система обозначения типов данных, которая соответствует типам данных в языках C и Fortran (соответствие неполное).
Тип данных MPI | Тип данных C |
MPI_CHAR | signed char |
MPI_SHORT | signed short int |
MPI_INT | signed int |
MPI_LONG | signed long int |
MPI_UNSIGNED_CHAR | unsigned char |
MPI_UNSIGNED_SHORT | unsigned short int |
MPI_UNSIGNED | unsigned int |
MPI_UNSIGNED_LONG | unsigned long int |
MPI_FLOAT | float |
MPI_DOUBLE | double |
MPI_LONG_DOUBLE | long double |
MPI_BYTE | Нет соответствия |
MPI_PACKED | Нет соответствия |
Привязка к языку Fortran
Все имена подпрограмм и констант MPI начинаются с MPI_. Коды завершения передаются через дополнительный параметр целого типа (находится на последнем месте в списке параметров подпрограммы). Код успешного завершения - MPI_SUCCESS.
Константы и другие объекты MPI описываются в файле mpi.h, который обязательно включается в MPI-программу с помощью оператора include. Этот оператор находится в начале программы.
Переменная status является массивом стандартного целого типа. Его размер и индексы задаются именованными константами:
integer status(MPI_STATUS_SIZE) ... if(status(MPI_TAG).EQ.tag1) then ...
В программах на языке Fortran такие объекты MPI, как MPI_Datatype или MPI_Comm - целого типа (integer).
В программах на языке C используются библиотечные функции MPI, в программах на языке Fortran - процедуры.
Структура MPI-программы
В программе MPI следует соблюдать определенные правила, без которых она окажется неработоспособной.
В начале программы, сразу после ее заголовка, необходимо подключить соответствующий заголовочный файл. В программе на языке C это mpi.h:
#include "mpi.h"
а в программе на языке Fortran - mpif.h:
include "mpif.h"
В этих файлах содержатся описания констант и переменных библиотеки MPI.
Первым вызовом библиотечной процедуры MPI в программе должен быть вызов подпрограммы инициализации MPI_Init, перед ним может располагаться только вызов MPI_Initialized, с помощью которого определяют, инициализирована ли система MPI. Вызов процедуры инициализации выполняется только один раз. В языке Fortran у процедуры инициализации единственный аргумент - код ошибки: integer IERR
call mpi_init(ierr)
В C параметры функции инициализации получают адреса аргументов главной программы, задаваемых при ее запуске:
MPI_Init(&argc, &argv);
Загрузчик mpirun в конец командной строки запуска MPI-программы добавляет служебные параметры, необходимые MPI_Init. В программах на языке Fortran аргументы командной строки не используются.
Процедура инициализации создает коммуникатор со стандартным именем MPI_COMM_WORLD. Это имя указывается во всех последующих вызовах процедур MPI.
После выполнения всех обменов сообщениями в программе должен располагаться вызов процедуры
MPI_Finalize(ierr)
В результате этого вызова удаляются структуры данных MPI и выполняются другие необходимые действия. Программист должен позаботиться о том, чтобы к моменту вызова процедуры MPI_Finalize были завершены все пересылки данных. После выполнения данного вызова другие вызовы процедур MPI, включая MPI_Init, недопустимы. Исключение составляет подпрограмма MPI_Initialized, которая возвращает значение "истина", если процесс вызывал MPI_Init. Данный вызов может находиться в любом месте программы.
Организация программы по схеме master-slave
program parallel … if (процесс = мастер) then master else slave endif … end
Простейшая MPI-программа
MPI_Iinit(int *argc, char **argv)
Аргументы argc и argv требуются только в программах на C, где они задают количество аргументов командной строки запуска программы и вектор этих аргументов. Данный вызов предшествует всем прочим вызовам подпрограмм MPI.
MPI_Finalize()
После вызова данной подпрограммы нельзя вызывать подпрограммы MPI. MPI_Finalize должны вызывать все процессы перед завершением своей работы
MPI_Comm_size(comm, size)
определение размера области взаимодействия.
comm - входной параметр-коммуникатор.
Выходным является параметр size целого типа - количество процессов в области взаимодействия
MPI_Comm_rank(comm, pid)
Здесь pid - идентификатор процесса в указанной области взаимодействия
Простейшая MPI-программа
simple_MPI.cpp
#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); printf("Hello world from process %i \n", ProcRank); MPI_Finalize(); return 0; }
simple_MPI.f90
program main_mpi include 'mpif.h' integer :: myid, numprocs, ierr call mpi_init(ierr) call mpi_comm_rank(mpi_comm_world, myid, ierr) call mpi_comm_size(mpi_comm_world, numprocs, ierr) print *, "process ", myid, " of ", numprocs call mpi_finalize(ierr) end program