Опубликован: 28.07.2007 | Доступ: свободный | Студентов: 2026 / 503 | Оценка: 4.53 / 4.26 | Длительность: 25:10:00
ISBN: 978-5-9556-0096-3
Специальности: Программист
Лекция 5:

Параллельное программирование на основе MPI

5.2. Введение в разработку параллельных программ с использованием MPI

5.2.1. Основы MPI

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

5.2.1.1. Инициализация и завершение MPI-программ

Первой вызываемой функцией MPI должна быть функция:

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

где

  • argc — указатель на количество параметров командной строки,
  • argv — параметры командной строки,

применяемая для инициализации среды выполнения MPI -программы. Параметрами функции являются количество аргументов в командной строке и адрес указателя на массив символов текста самой командной строки.

Последней вызываемой функцией MPI обязательно должна являться функция:

int MPI_Finalize(void).

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

#include "mpi.h"
int main(int argc, char *argv[]) {
 <программный код без использования функций MPI>
 MPI_Init(&argc, &argv);
 <программный код с использованием функций MPI>
 MPI_Finalize();
 <программный код без использования функций MPI>
 return 0;
}

Следует отметить:

  • файл mpi.h содержит определения именованных констант, прототипов функций и типов данных библиотеки MPI ;
  • функции MPI_Init и MPI_Finalize являются обязательными и должны быть выполнены (и только один раз) каждым процессом параллельной программы ;
  • перед вызовом MPI_Init может быть использована функция MPI_Initialized для определения того, был ли ранее выполнен вызов MPI_Init, а после вызова MPI_Finalize – MPI_Finalized2Эта функция появилась только в стандарте MPI версии 2.0. аналогичного предназначения.

Рассмотренные примеры функций дают представление синтаксиса именования функций в MPI. Имени функции предшествует префикс MPI, далее следует одно или несколько слов названия, первое слово в имени функции начинается с заглавного символа, слова разделяются знаком подчеркивания. Названия функций MPI, как правило, поясняют назначение выполняемых функцией действий.

5.2.1.2. Определение количества и ранга процессов

Определение количества процессов в выполняемой параллельной программе осуществляется при помощи функции:

int MPI_Comm_size(MPI_Comm comm, int *size),

где

  • comm — коммуникатор, размер которого определяется,
  • size — определяемое количество процессов в коммуникаторе.

Для определения ранга процесса используется функция:

int MPI_Comm_rank(MPI_Comm comm, int *rank),

где

  • comm — коммуникатор, в котором определяется ранг процесса,
  • rank — ранг процесса в коммуникаторе.

Как правило, вызов функций MPI_Comm_size и MPI_Comm_rank выполняется сразу после MPI_Init для получения общего количества процессов и ранга текущего процесса:

#include "mpi.h"
int main(int argc, char *argv[]) {
 int ProcNum, ProcRank;
 <программный код без использования функций MPI>
 MPI_Init(&argc, &argv);
 MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
 MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
   <программный код с использованием функций MPI>
 MPI_Finalize();
 <программный код без использования функций MPI>
 return 0;
}

Следует отметить:

  • коммуникатор MPI_COMM_WORLD, как отмечалось ранее, создается по умолчанию и представляет все процессы выполняемой параллельной программы ;
  • ранг, получаемый при помощи функции MPI_Comm_rank, является рангом процесса, выполнившего вызов этой функции, т. е. переменная ProcRank примет различные значения у разных процессов.
5.2.1.3. Передача сообщений

Для передачи сообщения процесс - отправитель должен выполнить функцию:

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

где

  • buf — адрес буфера памяти, в котором располагаются данные отправляемого сообщения;
  • count — количество элементов данных в сообщении;
  • type — тип элементов данных пересылаемого сообщения;
  • dest — ранг процесса, которому отправляется сообщение;
  • tag — значение-тег, используемое для идентификации сообщения;
  • comm — коммуникатор, в рамках которого выполняется передача данных.

Для указания типа пересылаемых данных в MPI имеется ряд базовых типов, полный список которых приведен в табл. 5.1.

Таблица 5.1. Базовые (пpедопpеделенные) типы данных MPI для алгоритмического языка C
Тип данных MPI Тип данных C
MPI_BYTE
MPI_CHAR signed char
MPI_DOUBLE double
MPI_FLOAT float
MPI_INT int
MPI_LONG long
MPI_LONG_DOUBLE long double
MPI_PACKED
MPI_SHORT short
MPI_UNSIGNED_CHAR unsigned char
MPI_UNSIGNED unsigned int
MPI_UNSIGNED_LONG unsigned long
MPI_UNSIGNED_SHORT unsigned short

Следует отметить:

  • отправляемое сообщение определяется через указание блока памяти (буфера), в котором это сообщение располагается. Используемая для указания буфера триада (buf, count, type) входит в состав параметров практически всех функций передачи данных;
  • процессы, между которыми выполняется передача данных, в обязательном порядке должны принадлежать коммуникатору, указываемому в функции MPI_Send ;
  • параметр tag используется только при необходимости различения передаваемых сообщений, в противном случае в качестве значения параметра может быть использовано произвольное положительное целое число3Максимально возможное целое число, однако, не может быть больше, чем определяемая реализацией константа MPI_TAG_UB . (см. также описание функции MPI_Recv ).

Сразу же после завершения функции MPI_Send процесс -отправитель может начать повторно использовать буфер памяти, в котором располагалось отправляемое сообщение. Также следует понимать, что в момент завершения функции MPI_Send состояние самого пересылаемого сообщения может быть совершенно различным: сообщение может располагаться в процессе -отправителе, может находиться в состоянии передачи, может храниться в процессе -получателе или же может быть принято процессом -получателем при помощи функции MPI_Recv. Тем самым, завершение функции MPI_Send означает лишь, что операция передачи начала выполняться и пересылка сообщения рано или поздно будет выполнена.

Пример использования функции будет представлен после описания функции MPI_Recv.