Примеры распределения работы между процессами

Семинар 2.

Тема: Технология MPI: функции для определения номера процесса и размера группы; распределение работы между процессами

 

План:

· Введение

· Функции для определения номера процесса и размера группы

· Примеры распределения работы между процессами

· Задания

 

Введение

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

Это означает, в частности, что любая объявленная переменная появляется в локальной памяти каждого процесса, задействованного для решения данной задачи.

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

Таким образом, если не предпринимать специальных усилий – каждый процесс выполнит все операции в программе. Мы это видели на примере простейшей программы «HELLO».

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

За счет того, что каждому процессу достается выполнить не всю работу, а только ее часть – можно ожидать уменьшения времени счета при использовании более чем одного процесса. Это называется ускорением вычислений.

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

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

Функции для определения номера процесса и размера группы

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

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

Запрос порядкового номера производится посредством обращения к функции:

int MPI_Comm_rank (MPI_Comm comm, int *rank)

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

Запрос количества процессов в группе (это обычно называют «размер группы») происходит по аналогичной схеме. За это отвечает функция

int MPI_Comm_size (MPI_Comm comm, int *size)

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

Пример

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

Здесь каждый процесс в своей локальной памяти объявляет целые переменные для записи номера процесса и количества процессов в группе.

int myid, numprocs;

Каждый процесс вызывает функции

MPI_Comm_size(MPI_COMM_WORLD,&numprocs);

MPI_Comm_rank(MPI_COMM_WORLD,&myid);

В результате по адресу myid в каждом процессе записывается его номер, в по адресу numprocs – количество процессов.

Далее каждые процесс печатает вои собственные переменные myid, numprocs.

Номер процесса (myid) у каждого свой, нумерация идет от 0, при печати порядок номеров может нарушаться, поскольку процессы работают параллельно и необязательно процесс, скажем, с номером 0 успеет первым напечатать свои данные.

Переменная numprocs – также у каждого процесса своя, но ее значения во всех процессах совпадают:

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

Примеры распределения работы между процессами

В рассмотренном примере, как и в примере на прошлом семинаре – каждый процесс выполнил все операции в программе.

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

Модифицируем предыдущий пример:

Здесь каждый процесс печатает свой номер, а количество процессов (размер группы) печатает только процесс с номером 0. Также, процесс, имеющий максимальный номер – печатает «HELLO».

Отметим, что максимальный номер – на 1 меньше размера группы, поскольку нумерация процессов осуществляется с 0.

Как видим, теперь разные процессы выполнили различные действия.

Рассмотрим теперь более общий пример – как можно в общем виде, без использования оператора if осуществить распараллеливание цикла, в котором на каждой итерации значение целочисленной переменной А=0 увеличивается на 1.

Один из вариантов – «блочное» распределение расчета между параллельными процессами. Поставим задачу написать программу в общем виде, чтобы схема распределения работала при любом количестве процессов, не превышающем размерность массива.

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

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

Пусть номер процесса хранится в переменной rank, начальные и конечные индексы блоков – в imin и imax соответственно.

     

КОЛИЧЕСТВО ИТЕРАЦИЙ В ЦИКЛЕ

Здесь ost – остаток, который назначается в работу процессу с максимальным номером, в случае, когда N не делится нацело на np.

При N=20 и np=4 каждый процесс с номером rank выполняет по del=N/np итераций, при этом переменная А в каждом процессе «пробегает» значения от 1 до del=5.

При запуске программы с другим количеством процессов переменная А в каждом процессе будет «пробегать» значения от 1 до del=N/np, за исключением последнего процесса, где А будет увеличиваться от 1 до del=N/np+ost. Предлагаем убедиться в этом самостоятельно.

Задания:

1. Изучить в учебном пособии по MPI разделы 2.1-2.3 Главы 2.

2. Воспроизвести на кластере HybriLIT рассмотренные примеры.

3. Составить и запустить программу, в которой процесс с номером 0 печатает слово «Hello», процесс с номером 1 печатает слово «Goodbye», процесс с номером 2 печатает количество процессов в группе, каждый процесс с номерами >2 печатают свои номер. Запустить программу с количеством процессов 1,2,3,4,5, объяснить результат, который видим на экране.


Дата добавления: 2021-04-05; просмотров: 277; Мы поможем в написании вашей работы!

Поделиться с друзьями:




Мы поможем в написании ваших работ!