Стандарт механизма передачи сообщений MPI (Message Passing Interface) был принят в 1994 г. Стандарт готовился с 1992 по 1994 годы. группой Message Passing Interface Forum. Основная цель, которую ставили перед собой разработчики MPI – обеспечение полной независимости программ, написанных с использованием библиотеки MPI, от архитектуры многопроцессорной системы.
Отметим, что интерфейс громоздок и сложен для прикладного программиста. Интерфейс также сложен для реализации. Поэтому практически отсутствуют реализации MPI, в которых в полной мере обеспечивается совмещение обменов с вычислениями.
В 1997 появился проект стандарта MPI-2, который выглядит еще более громоздким и трудным для полной реализации. Реализацией стандарта MPI-2 является библиотека MPI-2.
Рассмотрим достаточно характерный вычислительный алгоритм, реализующий метод релаксации Якоби для решения систем линейных алгебраических уравнений. Сравним размеры его последовательной версии и двух параллельных версий (MPI, HPF). Размер в строках последовательной программы на языке Fortran 77 равен 17, а размеры параллельных версий для MPI и HPF равны, соответственно, 55 и 24.
Общие сведения о MPI.
Отметим, прежде всего, что стандарт MPI не стандартизует реализацию. Поставщики многопроцессорных вычислительных систем, как правило, предлагают свои реализации стандарта MPI для своих машин. Однако правильная MPI-программа (программа, написанная с использованием MPI) должна одинаково выполняться на всех реализациях.
Существуют стандартные "привязки" MPI к языкам С/С++, Fortran 77/90, а также бесплатные и коммерческие реализации MPI почти для всех суперкомпьютерных платформ, а также для UNIX и Windows NT вычислительных кластеров. Переносимой версией библиотеки МРI является библиотека МРIСН.
MPI-программа представляет собой набор независимых процессов, каждый из которых выполняет свою собственную программу, написанную на каком-либо языке высокого уровня. Процессы MPI-программы взаимодействуют друг с другом посредством передачи сообщений путем вызова коммуникационных функций MPI-библиотеки. Как правило, каждый процесс выполняется в своем собственном адресном пространстве, однако допускается и режим разделения памяти. Стандарт MPI не специфицирует модель выполнения процесса — это может быть как последовательный процесс, так и многопотоковый.
MPI-библиотека реализована в виде примерно 130 функций, в число которых входят следующие основные наборы функций:
Набор функций библиотеки MPI далеко выходит за рамки набора функций, минимально необходимого для поддержки механизма передачи сообщений. Почти любая MPI-программа может быть написана с использованием всего 6 MPI-функций, а достаточно полную и удобную среду программирования составляет набор из 24 функций.
MPI не обеспечивает механизмов задания начального размещения процессов по процессорам. Предполагается, что для этого имеются другие средства. Эти средства должны позволять задать число процессоров и процессов, разместить процессы и данные на каждом процессоре.
Стандарт MPI требует, чтобы MPI-программы могли выполняться на гетерогенных многопроцессорных системах, в которых различные процессоры имеют различные форматы данных одного и того же типа. MPI-программа должна работать также на мультипроцессорных вычислительных системах.
Основными понятиями стандарта MPI являются:
Процесс – исполнение программы на одном процессоре. Процесс может содержать последовательный код, параллельные ветви, операции ввода/ вывода и пр.
Группа процессов – совокупность процессов, каждый из которых имеет внутри группы уникальное имя. Процессы в группе взаимодействуют посредством коммуникатора группы. Процессы в группе имеют номер от 0 до (n-1), где n – количество процессов в группе.
Коммуникатор реализует обмены данными между процессами и их синхронизацию. Для прикладной программы коммуникатор выступает в качестве коммуникационной среды. Различают внутригрупповые коммуникаторы (intra) и межгрупповые коммуникаторы (inter). Сообщения, использующие разные коммуникаторы, не оказывают влияния друг на друга и не взаимодействуют.
Функции для работы с группами процессов и коммуникаторами.
Группа конструируется из уже существующих групп путем операций над ними, как над множествами именованных процессов. Базовой группой является группа MPI_COMM_WORLD, которая создается при инициализации MPI-библиотеки. Группа MPI_COMM_WORLD содержит процессы с номерами , где n – число процессоров, определенное при инициализации.
Можно создать новую группу, перечислив образующие ее элементы уже существующей группы. Определены пересечение групп, объединение групп и другие теоретико-множественные операции.
Существует ряд процедур для определения процессом своего положения в группе. Например:
  1. процедура MPI_GROUP_SIZE(group, size) присваивает переменной size значение, равное числу процессов в группе с именем group;
  2. процедура MPI_GROUP_RANK(group, rank) присваивает переменной rank значение, равное номеру процесса в группе с именем group, который выполнил этот вызов.
Эффективность работы коммуникатора группы можно повысить, если явно указать информационные связи между процессами (топологию группы).
В стандарте MPI имеются средства для задании некоторых регулярных топологий групп (например, гиперкубов) и произвольных топологий группы.
Рассмотрим процедуру для задания произвольной топологии группы
MPI_GRAPH_CREATE (comm_old, nnodes, index, edges, reorder, comm_graph)
Здесь
comm_old – имя коммуникатора, соотнесенного с исходной топологией данной группы;
nnodes – число вершин графа информационных связей;
index – массив степеней вершин графа (число соседних с данной вершин);
edges – массив ребер графа;
reorder = TRUE;
comm_graphкоммуникатор, соответствующий группе с описанной топологией.
Пример 1
Пусть имеется 4 процесса (0, 1, 2, 3) с топологией информационных связей между ними, приведенной на Рис.1.
Рис. 1.  Топология информационных связей процессов Q0Q3.
Тогда
nnodes = 4;
index = 2, 1, 1, 2;
edges = 1, 3, 0, 3, 0, 2
MPI-библиотека имеет ряд функций, позволяющих программе пользователя определить параметры топологии группы. Например, можно определить число соседей указанного процессора и имена соседей.
Отметим, что топология группы определяет связи между процессами, но никак не физические связи между процессорами, на которых выполняются эти процессы.
Группы процессов являются мощным средством распараллеливания — позволяют разделить группу процессов на несколько подгрупп, каждая из которых выполняет свою параллельную процедуру. Коммуникаторы группы позволяют ограничить область видимости сообщений рамками некоторой группы процессов, что позволяет сократить накладные расходы на коммуникации.
Функции, реализующие коммуникационные операции типа точка-точка (парные обмены).
Основу взаимодействия процессов составляют следующие процедуры обмена сообщениями между процессами:
1) MPI_SEND(buf, count, datatype, dest, tag, comm)
buf – начальный адрес передающего буфера;
count — число передаваемых элементов в сообщении;
datatype — тип передаваемых элементов;
dest — номер принимающего процесса в группе с коммуникатором comm;
gtag — тэг сообщения;
comm – идентификатор коммуникатора группы, всем процессам которой посылается сообщение.
2) MPI_RECV (buf, count, datatype, source, tag, comm, status)
buf – начальный адрес приемного буфера;
count — число принимаемых элементов в сообщении;
datatype — тип принимаемых элементов;
source — номер процесса-отправителя в группе с коммуникатором comm;
tag — тэг сообщения
comm — идентификатор коммуникатора группы
status — параметры принятого сообщения.
Здесь
tag – целое число, которое используется для указания типа сообщения. В вызове процедуры MPI_RECV в качестве параметров source, tag можно использовать константы MPI_ANY_SOURCE, MPI_ANY_TAG, соответственно. При этом процедура MPI_RECV будет принимать сообщения от любых источников с любыми тэгами;
status – возвращает аргументы source, tag, а также длину принятого сообщения. Эти аргументы могут быть необходимы при приеме сообщения при использовании констант MPI_ANY_SOURCE, MPI_ANY_TAG.
Возможны два режима обмена сообщения с помощью процедур MPI_SEND, MPI_RECV – блокирующий (blocking) и не блокирующий (non blocking). В блокирующем режиме возврат из процедуры происходит после ее выполнения и освобождения всех ресурсов – синхронная модель простого рандеву. В не блокирующем режиме возврат из процедуры происходит до завершения ее выполнения и освобождения всех ресурсов – асинхронная модель передачи сообщений.
Блокировка гарантирует корректность повторного использования всех параметров после возврата из подпрограммы. Заметим, что стандарт MPI не определяет способ обеспечения этой гарантии: копирование в промежуточный буфер или непосредственная передача процессу dest. Заметим также, что в блокирующем режиме возврат из подпрограммы MPI_SEND не означает ни того, что сообщение уже передано процессу dest, ни того, что сообщение покинуло процессорный элемент, на котором выполняется процесс, выполнивший MPI_SEND
Функции, реализующие коллективные коммуникационные операции.
Коллективные коммуникационные операции выполняются всеми процессами данной группы (посредством вызова соответствующих процедур). Рассмотрим основные процедуры данного класса.
1) MPI_BCAST (buf, count, datatype, source, comm) осуществляет широковещательную (broadcast) передачу сообщения от одного процесса всем остальным процессам данной группы.
buf — адрес начала буфера посылки сообщения;
count — число передаваемых элементов в сообщении;
datatype — тип передаваемых элементов;
source — номер рассылающего процесса;
comm — идентификатор группы.
2) MPI_GATHER(sbuf, scount, stype, rbuf, rcount, rtype, dest, comm) осуществляет сбор данных от всех процессов группы в один из процессов группы.
sbuf — адрес начала буфера посылки;
scount — число элементов в посылаемом сообщении;
stype — тип элементов отсылаемого сообщения;
rbuf — адрес начала буфера сборки данных;
rcount — число элементов в принимаемом сообщении;
rtype — тип элементов принимаемого сообщения;
dest — номер процесса, на котором происходит сборка данных.
comm — идентификатор группы.
3) MPI_ALLGATHER() выполняет сбор данных от всех процессов группы и рассылку результата сборки всем процессам группы;
4) MPI_ALLTOALL() выполняет раздачу и, одновременно, сбор данных от всех процессов группы во все процессы группы.
Другие функции MPI.
  1. В MPI имеются средства для вычисления минимума, максимума, суммы и т.п. данных, которые распределены по процессорам системы. Подобные операции могут быть также определены пользователем.
  2. Средства обработки некоторых ошибок, которые возникают при выполнении функций MPI. Это могут быть, например, ошибки для операций с плавающей точкой или при нарушении прав доступа. В MPI имеется ряд предопределенных обработчиков ошибок:
Реализации могут обеспечивать дополнительные обработчики ошибок, программисты также могут написать свои собственные обработчики ошибок. Важно, что поскольку все функции MPI возвращают код ошибки, пользователь с помощью обработчиков ошибок может выполнять отладку MPI-программы или управлять ею.
Интерфейс MPI-2.
Уже упоминавшийся новый стандарт MPI-2 расширяет стандарт MPI, в основном, по следующим направлениям:
  1. Поддержка модели обмена данными "расширенное рандеву", что позволяет писать MPI-программы не только для расчетных математических задач, но и для системы массового обслуживания.
  2. Динамическое порождение процессов. Для программирования расчетных задач это средство вряд ли нужно, однако оно необходимо для разработки систем массового обслуживания.
  3. Средства работы процесса с файлами, которые расположены на жестких дисках другого процессора (параллельное чтение/ запись).
  4. Возможность использовать разделяемую память мультипроцессора не только для обмена данными между процессами, но и для совместного хранения данных (механизм односторонних коммуникаций ("one-sided communications")).