Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Хьюз Камерон. Параллельное и распределенное программирование на С++ - royallib.ru.doc
Скачиваний:
119
Добавлен:
11.03.2016
Размер:
1.97 Mб
Скачать

Декомпозиция работ для mpi-интерфейса

Одним из преимуществ использования MPI-интерфейса перед традиционными UNIX/Linux-процессами и сокетами является способность MPI-среды запускать одновременно несколько выполняемых файлов. MPI-реализация может запустить несколько выполняемых файлов, установить между ними базовые отношения и идентифицировать каждый выполняемый файл. В этой книге мы используем MPICH-реализацию MPI-интерфейса 171. При выполнении команды$ mpirun -np 16 /tmp/mpi_example1 будет запущено 16 процессов. Каждый процесс будет выполнять программу с именем mpi_example1. Все процессы могут использовать разные доступные процессоры. Кроме того, каждый процесс может выполняться на отдельном компьютере, если MPI работает в среде кластерного типа. Процессы при этом будут выполняться параллельно. Команда mpirun представляет собой основной сценарий, который отвечает за запуск MPI-заданий на необходимом количестве процессоров. Этот сценарий изолирует пользователя от подробностей запуска параллельных процессов на различных компьютерах. Здесь будет запущено 16 копий программы mpi_examplel. Несмотря на то что стандарт MPI-2 определяет функции порождения, которые можно использовать для динамического добавления программ к выполняемому MPI-приложению, этот метод не популярен. В общем случае необходимое количество процессов создается при запуске MPI-приложения. Следовательно, во время старта этот код тиражируется N раз. Описаннал схема легко поддерживает модель параллелизма SPMD (SIMD), поскольку одна и та же программа запускается одновременно на нескольких процессорах. Данные, с которыми каждой программе нужно работать, определяются после запуска программ. Этот метод старта одной и той же программы на нескольких процессорах можно развить, если нужно реализовать модель MPMD. Вся работа MPI-программы делится между несколькими процессами, запускаемыми на старте программы. Информация о распределении «обязанностей» (т.е. кто что делает и какие процессы работают с какими данными) содержится в самой выполняемой программе. Компьютеры, задействованные в этой работе, перечис л яются в файле machines.arch (machines.Linux в данно м случае) с использование м и м ени ко м пьютера. Местоположение это г о файла зависит от конкретной реализации. В зависи м ости от инсталляции, взаи м одействие ко м пьютеров, перечисленных в это м файле, будет обеспечено либо ко м андой ssh, либо UNIX/Linux-ко м андой ' r'.

Дифференциация задач по рангу

Во время старта процессов, включенных в MPI-приложение, МРI-среда назначает каждому процессу ранг и группу коммуникации. Ранг хранится как int-значение и служит в качестве идентификатора процесса для каждой MPI-задачи. Группа коммуникации определяет, какие процессы можно включить во взаимодействие типа «точка-точка». Сначала все MPI-процессы относят к группе, действующей по умолчанию. Заменить членов группы коммуникации можно, запустив приложения. После старта каждого процесса необходимо определить его ранг с помощью функции MPI_Comm_rank (). Функция MPI_Comm_rank () возвращает ранг вызывающего процесса. В первом аргументе, передаваемом функции, вызывающий процесс определяет, с каким коммуникатором он связывается, а его ранг возвращается во втором аргументе. Пример использования функции MPI_Comm_rank () показан в листинге 9.1.

// Листинг 9.1. Использование функции MPI_Comm_rank() //.. .

int Tag = 33;

int WorldSize;

int TaskRank;

MPI_Status Status;

MPI_Init (&argc, &argv) ;

MPI_Comm_rank(MPI_COMM_WORLD, &TaskRank) ; MPI_Comm_size(MPI_COMM_WORLD, &WorldSize) ; //.. .

Коммуникатору MPI_COMM_WORLD по умолчанию при запуске назначаются все MPI-задачи. MPI-задачи группируются по коммуникаторам, которые определяют группу коммуникации. В листинге 9.1 ранг возвращается в переменной TaskRank. Каждый процесс должен иметь уникальный ранг. После определения ранга задаче передаются соответствующие данные либо определяется код, который ей надлежит выполнить. Рассмотрим следующие варианты.

Вариант 1. Простая MPMD-модель   Вариант 2. Простая SIMD-модель

if(TaskRank == 1){   if(TaskRank == 1){

// Некоторые действия.   // Используем одни данные.

}   }

if (TaskRank == 2){   if(TaskRank == 2){

// Другие действия.   // Используем другие данные.

}   }

В первом варианте ранг используется для разграничения между процессами выполняемой работы, а во втором — для разграничения данных, которые они должны обрабатывать. Несмотря на то что каждый выполняемый MPI-файл стартует с одним и тем же кодом, модель MPMD (MIMD) можно реализовать с помощью рангов и соответствующего ветвления программы. Аналогично после определения ранга данным процесса можно назначить некоторый тип, тем самым определив конкрет-ные данные, с которыми должен работать конкретный процесс. Ранг также используется при передаче сообщений. MPI-задачи идентифицируют одна другую при обмене сообщениями по рангам и ко мм уникатора м. Функции MPI_Send () | MPI_Recv() используют ранг в качестве указания пунктов назначения и отправления соответственно. При выполнении вызова

MPI_Send(Buffer,Count, MPI_LONG, TaskRank, Tag,Comm) ;

будет отправлено Count значений типа long MPI-процессу с рангом, равным значению TaskRank. Параметр Buffer представляет собой указатель на данные, посылаемые процессу TaskRank. Параметр Count характеризует количество элементов в буфере Buffer, а не его раз м ер. Каждое сообщение имеет тег. Этот тег позволяет отличить одно сообщение от другого, сгруппировать сообщения в классы, связать определенные сообщения с определенными коммуникаторами и пр. Тег имеет тип int, а его значение определяется пользователем. Параметр Comm представляет коммуникатор, которому назначается процесс. Если ранг и коммуникатор задачи известны, этой задаче можно посылать сообщения. При выполнении вызова

MPI_Recv(Buffer, Count, MPI_INT, TaskRank, Tag, Comm, &Status);

будет получено Count значений типа int от процесса с рангом TaskRank. Инициатор вызова будет заблокирован до тех пор, пока не получит сообщение от процесса с рангом TaskRank и соответствующим значением тега (Tag). MPI-интерфейс для параметров ранга и тега поддерживает групповые символы. Такими групповыми символами являются значения MPI_ANY_TAG и MPI_ANY_SOURCE. При использовании этих значений вызывающий процесс примет следующее полученное им сообщение независимо от его источника и тега. Параметр Status имеет тип MPI_Status. Информацию об операции приема можно получить из объекта Status. Параметр статуса содержит три поля: MPI_SOURCE, MPI_TAG и MPI_ERROR. Следовательно, объект Status можно использовать для определения тега и источника процесса-отправителя. При известном количестве процессов-участников можно точно определить отправителей сообщений и их получателей. Обычно для этого используется конкретное приложение. Распределение работы также зависит от приложения. Перед началом работы каждый процесс сразу же определяет, сколько других процессов включено в приложение. Это реализуется следующим вызовом: MPI_Comm_size(MFI_COMM_WORLD, &WorldSize) ;

С помощью этой функции определяется размер группы процессов, связанных с конкретным коммуникатором. В данном используется стандартный коммуникатор (MPI_COMM_WORLD). Количество процессов-участников возвращается в параметре WorldSize. Этот параметр имеет тип int. Если каждому процессу известно значение WorldSize, значит, он знает, сколько процессов связано его коммуникатором.