Опубликован: 28.10.2009 | Доступ: свободный | Студентов: 516 / 40 | Оценка: 4.67 / 4.39 | Длительность: 20:33:00
Лекция 4:

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

Аннотация: Лекция посвящена рассмотрению методов параллельного программирования для вычислительных систем с распределенной памятью с использованием MPI.
Ключевые слова: система с распределенной памятью, интерфейс, распределенные вычисления, MPI, операции передачи данных, переносимость, максимальная степень, ПО, многопроцессорные вычислительные системы, работ, workshop, message passing, distributed memory, environment, группа, forum, программные средства, контекст, алгоритмический язык, режимы передачи, группа процессов, коммуникатор, intercommunication, производный тип данных, полный граф, параллельные алгоритмы, коммуникационная сеть, виртуальные топологии, именованная константа, прототип функции, comms, DataType, unsigned, блок памяти, пересылка сообщений, код завершения, вычислительный эксперимент, латентность, редукция, no-op, битовые операции, отправитель сообщения, инициация, завершение операций, тупиковая ситуация, операции, размер сообщения, умножение матриц, частичный результат, удобство использования, вектор, список, множества, понятность, базовый тип данных, производный тип, extent, адрес переменной, размерность массива, indicator, структурный способ, аннулирование, объект, group, ranking, операция объединения, топология, представление, адресация процессов, решение дифференциального уравнения, частная производная, dimmed, period, reordering, DST, операции сдвига, дуга графа, матрица инцидентности, neighboring, Профилирование, локальные режимы, кластерная система, исполнение, Синхронный, информация, ресурс, Интернет, матричные вычисления, скалярное произведение

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

Решение всех перечисленных вопросов и обеспечивает интерфейс передачи данных ( message passing interface - MPI ).

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

    Подобный способ организации параллельных вычислений получил наименование модели "одна программа множество процессов" ( single program multiple processes or SPMP ) ).

  2. Для организации информационного взаимодействия между процессорами в самом минимальном варианте достаточно операции приема и передачи данных (при этом, конечно, должна существовать техническая возможность коммуникации между процессорами - каналы или линии связи ) В MPI существует целое множество операций передачи данных. Они обеспечивают разные способы пересылки данных, реализуют практически все рассмотренные в разделе 3 коммуникационные операции. Именно данные возможности является наиболее сильной стороной MPI (об этом, в частности свидетельствует и само название MPI).

Следует отметить, что попытки создания программных средств передачи данных между процессорами начались предприниматься практически сразу с появлением локальных компьютерных сетей - ряд таких средств, представлен, например, в Воеводин В.В. и Воеводин Вл.В. (2002), Buyya (1999), Andrews (2000) и многих других. Однако подобные средства часто были неполными и, самое главное, являлись несовместимыми. Таким образом, одна из самых серьезных проблем в программировании - переносимость программ при переводе программного обеспечения на другие компьютерные системы - проявлялась при разработке параллельных программ в самой максимальной степени. Как результат, уже с 90-х годов стали предприниматься усилия по стандартизации средств организации передачи сообщений в многопроцессорных вычислительных системах. Началом работ, непосредственно приведшей к появлению MPI, послужило проведение рабочего совещания по стандартам для передачи сообщений в среде распределенной памяти (the Workshop on Standards for Message Passing in a Distributed Memory Environment, Williamsburg, Virginia, USA, April 1992). По итогам совещания была образована рабочая группа, позднее преобразованная в международное сообщество MPI Forum, результатом деятельности которых явилось создание и принятие в 1994 г. стандарта интерфейса передачи сообщений ( message passing interface - MPI ) версии 1.0. В последующие годы стандарт MPI последовательно развивался. В 1997 г. был принят стандарт MPI версии 2.0.

Итак, теперь можно пояснить, что означает понятие MPI. Во-первых, MPI - это стандарт, которому должны удовлетворять средства организации передачи сообщений. Во-вторых, MPI - это программные средства, которые обеспечивают возможность передачи сообщений и при этом соответствуют всем требованиям стандарта MPI. Так, по стандарту, эти программные средства должны быть организованы в виде библиотек программных модулей ( библиотеки MPI ) и должны быть доступны для наиболее широко используемых алгоритмических языков C и Fortran. Подобную "двойственность" MPI следует учитывать при использовании терминологии. Как правило, аббревиатура MPI используется для упоминания стандарта, а сочетание "библиотека MPI" указывает на ту или иную программную реализацию стандарта. Однако достаточно часто для краткости обозначение MPI используется и для библиотек MPI и, тем самым, для правильной интерпретации термина следует учитывать контекст.

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

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

6.1 MPI: основные понятия и определения

Рассмотрим ряд понятий и определений, являющихся основополагающими для стандарта MPI.

6.1.1. Понятие параллельной программы

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

Каждый процесс параллельной программы порождается на основе копии одного и того же программного кода ( модель SPMP ). Данный программный код, представленный в виде исполняемой программы, должен быть доступен в момент запуска параллельной программы на всех используемых процессорах. Исходный программный код для исполняемой программы разрабатывается на алгоритмических языках C или Fortran с использованием той или иной реализации библиотеки MPI.

Количество процессов и число используемых процессоров определяется в момент запуска параллельной программы средствами среды исполнения MPI-программ и в ходе вычислений меняться не может. Все процессы программы последовательно перенумерованы от 0 до np-1, где np есть общее количество процессов. Номер процесса именуется рангом процесса.

6.1.2. Операции передачи данных

Основу MPI составляют операции передачи сообщений. Среди предусмотренных в составе MPI функций различаются парные ( point-to-point ) операции между двумя процессами и коллективные ( collective ) коммуникационные действия для одновременного взаимодействия нескольких процессов.

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

Как уже отмечалось ранее, стандарт MPI предусматривает необходимость реализации большинства основных коллективных операций передачи данных - см. подразделы 6.2 и 6.4.

6.1.3. Понятие коммуникаторов

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

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

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

При необходимости передачи данных между процессами из разных групп необходимо создавать глобальный коммуникатор ( intercommunicator ).

Подробное рассмотрение возможностей MPI для работы с группами и коммуникаторами будет выполнено в подразделе 6.6.

6.1.4. Типы данных

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

Подробное рассмотрение возможностей MPI для работы с производными типами данных будет выполнено в подразделе 6.5.

6.1.5. Виртуальные топологии

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

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

В MPI имеется возможность представления множества процессов в виде решетки произвольной размерности (см. рис. 6.7). При этом, граничные процессы решеток могут быть объявлены соседними и, тем самым, на основе решеток могут быть определены структуры типа тор.

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

И, наконец, последний ряд замечаний перед началом рассмотрения MPI:

  • Описание функций и все приводимые примеры программ будут представлены на алгоритмическом языке C; особенности использования MPI для алгоритмического языка Fortran будут даны в п. 6.8.1,
  • Краткая характеристика имеющихся реализаций библиотек MPI и общее описание среды выполнения MPI программ будут рассмотрены в п. 6.8.2,
  • Основное изложение возможностей MPI будет ориентировано на стандарт версии 1.2 ( MPI-1 ); дополнительные свойства стандарта версии 2.0 буду представлены в п. 6.8.3.

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

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

6.2.1 Основы MPI

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

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

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

int MPI_Init ( int *agrc, char ***argv ).

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

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

int MPI_Finalize (void)

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

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

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

  1. Файл mpi.h содержит определения именованных констант, прототипов функций и типов данных библиотеки MPI,
  2. Функции MPI_Init и MPI_Finalize являются обязательными и должны быть выполнены (и только один раз) каждым процессом параллельной программы,
  3. Перед вызовом MPI_Init может быть использована функция MPI_Initialized для определения того, был ли ранее выполнен вызов MPI_Init.

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

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

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

int MPI_Comm_size ( MPI_Comm comm, int *size ).

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

int MPI_Comm_rank ( MPI_Comm comm, int *rank ).

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

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

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

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