Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практикум по параллельному программированию с использованием электронного задачника Programming Taskbook for MPI
.pdf
111
комиться с этой возможностью, импортируем в группу MPIDemo задание
MPIBegin83 — первое из заданий группы MPIBegin, посвященное вирту-
альным топологиям.
При импортировании существующего задания не требуется описывать
дополнительные процедуры; достаточно в основной процедуре группы вызвать процедуру UseTask:
procedure InitTask(num: integer); stdcall;
begin
case num of
1: MPIDemo1;
2: MPIDemo2;
3: MPIDemo3;
4: UseTask('MPIBegin', 83);
end;
end;
Первый (строковый) параметр процедуры UseTask определяет существующую группу, из которой импортируется задание, второй (числовой)
параметр — номер импортируемого задания. Никаких особых действий,
связанных с загрузкой указанной группы заданий, выполнять не требуется,
поскольку задачник выполняет эту загрузку автоматически. Необходимо
лишь, чтобы динамическая библиотека с реализацией этой группы (в нашем случае — PT4MPIBegin.dll) содержалась либо в подкаталоге LIB системного каталога задачника, либо в рабочем каталоге учащегося.
Как обычно, после включения в группу нового задания надо откорректировать предпоследний параметр процедуры CreateGroup, увеличив
его на 1.
Запустив наш проект на выполнение, мы увидим в окне задачника
описание импортированного задания (рис. 31).
Рис. 31. Демонстрационный запуск задания MPIDemo4

112 Часть II. Разработка новых учебных заданий
Возможность импортирования заданий полезна, если требуется перегруппировать имеющиеся задания, исключив некоторые из них (слишком
простые или слишком сложные) и/или изменив порядок их следования.
Группы, целиком состоящие из импортированных заданий, называются
сводными группами. Для создания таких групп в задачнике предусмотрен
специальный механизм, не требующий разработки проектов в средах
Borland Delphi или Free Pascal Lazarus. Достаточно подготовить текстовый
файл, указав в нем в определенном формате необходимые данные о новой
сводной группе (название и описание группы, имена включаемых в нее заданий), и обработать его с помощью программы PTVarMaker «Конструктор вариантов» (данная программа, как и конструктор учебных заданий,
входит в комплекс Teacher Pack for PT4). В результате на основе указанных
данных будет автоматически сгенерирована динамическая библиотека с
реализацией сводной группы (подробное описание механизма быстрого
создания сводных групп содержится в [1]).
Заканчивая разработку нашей демонстрационной группы, воспользуемся еще одной возможностью, предусмотренной в конструкторе учебных
заданий, — добавлением в группу дополнительных комментариев. Эти
комментарии не отображаются в окне задачника, однако указываются в качестве преамбулы в начале html-описания группы, которое можно сгенерировать, например, с помощью программного модуля PT4Demo.
Комментарии можно добавлять не только к группе, но и к ее отдельным подгруппам. Кроме того, комментарии, как и задания, можно импортировать из других групп.
Продемонстрируем различные способы добавления комментариев.
Добавим к создаваемой нами группе преамбулу, часть которой будет импортирована из группы MPIBegin. Кроме того, добавим преамбулу к подгруппе «Виртуальные топологии», в которой укажем, что содержащееся в
ней задание MPIDemo4 импортировано из группы MPIBegin.
Все действия по добавлению комментариев следует выполнять в процедуре инициализации группы inittaskgroup. Добавим в конец этой процедуры (после вызова процедуры CreateGroup) следующие операторы:
CommentText('Данная группа демонстрирует различные возможности');
CommentText('конструктора \MPT4TaskMaker\m при разработке');
CommentText('заданий по параллельному программированию.\P');
UseComment('MPIBegin');
Subgroup('Виртуальные топологии');
CommentText('Данное задание дублирует задание MPIBegin83.');
Три первых вызова процедуры CommentText определяют начальную
часть преамбулы для группы MPIDemo. Обратите внимание на управляю-
щие последовательности: парные последовательности
\M и \m выделяют
фрагмент, в котором используется моноширинный шрифт, а последовательность
\P обеспечивает переход к новому абзацу.

113
Процедура UseComment импортирует преамбулу группы MPIBegin и
добавляет ее к преамбуле нашей группы. Заметим, что если бы мы не использовали управляющую последовательность
\P в предыдущем вызове
процедуры CommentText, то первый абзац импортированной преамбулы
считался бы продолжением предыдущего абзаца преамбулы нашей группы. Заметим также, что имеется вариант процедуры UseComment, позволяющий импортировать преамбулу подгруппы; в этом варианте следует
указать два параметра: имя группы и заголовок требуемой подгруппы,
входящей в эту группу.
Последующий вызов процедуры Subgroup устанавливает режим определения преамбулы для подгруппы с указанным именем, после чего текст
этой преамбулы определяется с помощью еще одного вызова процедуры
CommentText.
Для того чтобы ознакомиться с результатом сделанных изменений,
следует сгенерировать html-страницу с текстом группы MPIDemo. Для этого достаточно внести небольшое изменение в параметры командной строки главного приложения PT4Demo.exe, дополнив параметр –g символом
#
(в результате список параметров примет вид
-gMPIDemo# -n999). Теперь при
запуске проекта PT4MPIDemo на экране вместо окна задачника с заданием
MPIDemo4 будет отображаться html-браузер с описанием созданной группы (см. рис. 32; обратите внимание на два последних абзаца в преамбуле
группы, которые был импортированы из группы MPIBegin).
Примечание. Для генерации html-описания группы заданий с помо-
щью программного модуля PT4Demo не обязательно использовать па-
раметры командной строки. Достаточно запустить программу
PT4Demo.exe с помощью ярлыка Demo.lnk, содержащегося в рабочем
каталоге, выбрать из списка групп нужную группу и нажать клавишу
[F2] или кнопку в окне данной программы. Вывести html-описание
группы можно также с помощью программы-заготовки, созданной для
выполнения задания. Для этого достаточно изменить параметр в про-
цедуре Task, удалив в нем номер и добавив символ #, например,
Task('MPIDemo#'). Заметим, что если указать в параметре символ #,
не удаляя номер задания (например, Task('MPIDemo4#')), то в html-
описание будет включено только задание с указанным номером. При
этом будут также выведены комментарии ко всей группе и к той под-
группе, к которой относится выбранное задание.
6.6. Особенности оформления группы заданий
в виде модуля среды PascalABC.NET
Если новую группу заданий предполагается использовать только в
среде PascalABC.NET, то ее можно реализовать не в виде dll-файла, а в виде pcu-файла, т. е. модуля языка Паскаль, откомпилированного в данной
программной среде.

114 Часть II. Разработка новых учебных заданий
Рис. 32. Страница html-браузера с описанием группы заданий MPIDemo
Для оформления описанной выше группы MPIDemo в виде модуля
языка Паскаль достаточно изменить файл PT4MPIDemo.dpr следующим
образом:
• заменить расширение данного файла на .pas;
• в заголовке программы заменить слово library на unit;
• в заголовке процедуры InitTask удалить модификатор stdcall вместе
с указанной после него точкой с запятой;
• в конец процедуры inittaskgroup добавить оператор
RegisterGroup('PT4MPIDemo');
• удалить строку, начинающуюся со слова exports;

115
• добавить в завершающий блок вызов процедуры inittaskgroup:
begin
inittaskgroup;
end.
Для того чтобы группа MPIDemo была доступна для использования,
необходимо откомпилировать файл PT4MPIDemo.pas в среде PascalABC.NET и разместить полученный модуль PT4MPIDemo.pcu либо в
рабочем каталоге учащегося, либо в подкаталоге Lib системного каталога
PascalABC.NET. К программе, предназначенной для выполнения задания
из данной группы, следует подключать (в любом порядке) не только модули PT4 и MPI, но и модуль PT4MPIDemo, содержащий реализацию этой
группы:
uses PT4MPIDemo, PT4, MPI;
Вызов процедуры RegisterGroup, добавленный в конец процедуры
inittaskgroup, позволяет зарегистрировать созданную группу заданий в
среде PascalABC.NET (см. [1, п. 2.5]). После регистрации группы MPIDemo
(для этого достаточно, чтобы хотя бы один раз была запущена программа,
подключившая модуль PT4MPIDemo) для заданий данной группы можно
будет автоматически создавать заготовки с помощью программного модуля PT4Load, интегрированного в среду PascalABC.NET. Благодаря наличию префикса MPI в имени группы, созданная заготовка будет учитывать
особенности заданий по параллельному MPI-программированию (см. пример программы-заготовки для языка Паскаль, приведенный в п. 2.2). Кроме
того, в список uses созданной заготовки будет автоматически добавлено
имя модуля PT4MPIDemo, содержащего реализацию требуемой группы.
В отличие от групп, реализованных в виде динамических библиотек
(dll-файлов), группы заданий, определенные в pcu-файлах, не распознаются программным модулем PT4Demo, интегрированным в среду
PascalABC.NET. Следует также иметь в виду, что если группа заданий с
одним и тем же именем реализована и в виде dll-файла и в виде pcu-файла,
то программный модуль PT4Load использует dll-вариант группы как более
универсальный (при этом к программе учащегося подключаются только
модули PT4 и MPI). В подобной ситуации для выбора pcu-варианта группы
достаточно указать имя соответствующего pcu-модуля в списке uses.

116 Часть III. Справочные сведения
Часть III
Справочные сведения
7. Основные типы, константы и функции
библиотеки MPI
Приведенное в данном разделе описание библиотеки MPI для языка C
соответствует стандарту MPI-1.1 (см. [7]). Стандарта MPI для языка Паскаль не существует; в настоящем пособии описывается реализация библиотеки MPI для Паскаля в виде модуля MPI.pas, выполненная автором и
включенная в электронный задачник Programming Taskbook for MPI. Все
функции, описанные в модуле MPI.pas, импортируются из динамической
библиотеки mpich.dll, входящей в комплекс MPICH для Windows.
В данном разделе описываются 102 функции MPI (из примерно 130
функций, входящих в стандарт MPI-1.1) и связанные с ними типы и константы. Не описаны функции, относящиеся, в основном, к следующим разделам стандарта MPI-1.1:
• работа с интеркоммуникаторами (см. [7, п. 5.6]);
• настройка атрибутов для коммуникаторов (см. [7, п. 5.7]);
• обработка ошибок (см. [7, п. 7.2–7.3]).
Для каждой функции вначале приводятся ее заголовки на языках С и
Паскаль, затем описываются ее параметры, после чего дается краткое описание самой функции. Возвращаемые значения функций не описываются,
так как любая функция MPI (кроме MPI_Wtime и MPI_Wtick) возвращает
информацию об успешности своего выполнения (в частности, при успешном завершении функция возвращает значение MPI_SUCCESS).
При описании параметров функций используются следующие обозначения: IN — параметр является входным, OUT — параметр является выходным, INOUT — параметр является входным и выходным. В функциях,
связанных с коллективным взаимодействием процессов, обозначение
INOUT может означать, что для некоторых процессов данный параметр
используется как входной, а для других — как выходной.
Быстро найти описание требуемой функции можно по алфавитному
указателю функций MPI, приведенному в конце пособия.
7.1. Типы и константы библиотеки MPI
MPI_Datatype (тип)
Определяет тип пересылаемых данных. Переменные этого типа являются дескрипторами, связанными либо со стандартными типами данных,
включенными в библиотеку MPI, либо с пользовательскими типами, опре-

117
деленными с помощью соответствующих функций MPI (см. п. 7.7). Ниже
перечислены константы, связанные со стандартными типами данных MPI
(в скобках указан соответствующий тип языка C):
MPI_SHORT (signed short int);
MPI_INT (signed int);
MPI_LONG (signed long int);
MPI_UNSIGNED_SHORT (unsigned short int);
MPI_UNSIGNED (unsigned int);
MPI_UNSIGNED_LONG (unsigned long int);
MPI_FLOAT (float);
MPI_DOUBLE (double);
MPI_LONG_DOUBLE (long double);
MPI_CHAR (signed char);
MPI_UNSIGNED_CHAR (unsigned char);
MPI_DATATYPE_NULL — данная константа записывается в дескриптор
пользовательского типа при уничтожении этого типа функцией
MPI_Type_free.
MPI_Request (тип)
Определяет идентификаторы приема или передачи («запросы обмена»), которые используются при неблокирующих взаимодействиях (см.
п. 7.4–7.5). Переменные этого типа являются дескрипторами. С данным
типом связана единственная константа MPI_REQUEST_NULL, обозначающая пустой запрос. Переменная типа MPI_Request принимает значение
MPI_REQUEST_NULL в результате обработки связанного с ней запроса
или его удаления функцией MPI_Request_free.
MPI_Comm (тип)
Определяет коммуникаторы, используемые при пересылке данных.
Переменные этого типа являются дескрипторами, связанными либо со
стандартными коммуникаторами, либо с пользовательскими коммуникаторами, определенными с помощью соответствующих функций MPI (см.
п. 7.8). Ниже перечислены константы, связанные со стандартными коммуникаторами:
MPI_COMM_WORLD — коммуникатор, включающий все процессы парал-
лельного приложения;
MPI_COMM_SELF — коммуникатор, включающий только текущий про-
цесс;
MPI_COMM_NULL — значение, используемое для указания ошибочного
коммуникатора.
При определении типа виртуальной топологии для данного коммуникатора (с помощью функции MPI_Topo_test) результат возвращается в виде одной из следующих целочисленных констант:
MPI_CART — с данным коммуникатором связана декартова топология;

118 Часть III. Справочные сведения
MPI_GRAPH — с данным коммуникатором связана топология графа;
MPI_UNDEFINED — с данным коммуникатором не связана никакая вир-
туальная топология.
При сравнении коммуникаторов функцией MPI_Comm_compare результат возвращается в виде одной из следующих целочисленных констант:
MPI_IDENT — два дескриптора указывают на один и тот же коммуника-
тор;
MPI_CONGRUENT — два различных коммуникатора содержат одинаковые
наборы одинаково упорядоченных процессов;
MPI_SIMILAR — два коммуникатора содержат одинаковые наборы про-
цессов, однако порядок расположения процессов в них различается;
MPI_UNEQUAL — два коммуникатора содержат различные наборы про-
цессов.
MPI_Group (тип)
Определяет группы процессов, используемые при пересылке данных.
Переменные этого типа являются дескрипторами, связанными либо со
стандартными группами, либо с пользовательскими группами, определенными с помощью соответствующих функций MPI (см. п. 7.8). Ниже перечислены константы, связанные со стандартными группами:
MPI_GROUP_EMPTY — группа, не содержащая элементов;
MPI_GROUP_NULL — значение, используемое для указания ошибочной
группы.
При сравнении групп функцией MPI_Group_compare результат возвращается в виде одной из следующих целочисленных констант:
MPI_IDENT — две группы содержат одинаковые наборы процессов,
причем эти наборы одинаково упорядочены;
MPI_SIMILAR — две группы содержат одинаковые наборы процессов,
однако порядок расположения процессов в них различается;
MPI_UNEQUAL — две группы содержат различные наборы процессов.
MPI_Op (тип)
Определяет операцию («операцию редукции»), используемую при
выполнении коллективной пересылки данных. Переменные этого типа являются дескрипторами, связанными либо со стандартными операциями,
либо с пользовательскими операциями, определенными с помощью соответствующих функций MPI (см. п. 7.6). Ниже перечислены константы, связанные со стандартными операциями редукции:
MPI_MAX — операция нахождения максимального значения;
MPI_MIN — операция нахождения минимального значения;
MPI_SUM — операция вычисления суммы;
MPI_PROD — операция вычисления произведения;
MPI_LAND — операция «логическое И»;

119
MPI_BAND — операция «побитовое И»;
MPI_LOR — операция «логическое ИЛИ»;
MPI_BOR — операция «побитовое ИЛИ»;
MPI_LXOR — операция «логическое исключающее ИЛИ»;
MPI_BXOR — операция «побитовое исключающее ИЛИ»;
MPI_MAXLOC — операция нахождения максимума и его индекса;
MPI_MINLOC — операция нахождения минимума и его индекса.
MPI_Aint (тип)
Тип, предназначенный для хранения адресов, а также смещений между различными адресами в памяти. Реализован как знаковый целочисленный тип, размер которого является достаточным для хранения любого адреса.
MPI_Status (тип)
Структурный тип, предназначенный для хранения дополнительной
информации, связанной с уже принятым или ожидающим принятия сообщением. Все поля типа MPI_Status являются целочисленными.
С помощью непосредственного обращения к полям данного типа
можно определить ранг процесса, пославшего сообщение (поле
MPI_SOURCE), идентификатор («метку») сообщения (поле MPI_TAG) и
код ошибки, связанной с данным сообщением (поле MPI_ERROR). Кроме
того, тип MPI_Status содержит дополнительное поле (в реализации MPICH
имеющее имя count), позволяющее определить количество элементов в сообщении. Вместо непосредственного обращения к данному полю следует
использовать функцию MPI_Get_count.
C посылкой и приемом сообщений связаны также следующие константы целого типа:
MPI_PROC_NULL — используется для посылки сообщения несуществу-
ющему процессу;
MPI_ANY_SOURCE — используется для приема сообщения от любого
процесса;
MPI_ANY_TAG — используется для приема сообщения с любым иденти-
фикатором;
MPI_TAG_UB — позволяет определить максимально допустимое значе-
ние для идентификатора сообщения;
MPI_BSEND_OVERHEAD — позволяет определить размер служебной части
буфера, используемого при передаче буферизованных сообщений.
MPI_User_function (тип)
Прототип функции в C/C++ (процедурный тип в Паскале), используемый при определении новой операции с помощью функции
MPI_Op_create. Определен следующим образом:
typedef void MPI_User_function(void* invec, void* inoutvec,
int* len, MPI_Datatype* datatype);

120 Часть III. Справочные сведения
type MPI_User_function = procedure(invec: pointer; inoutvec:
pointer; var len: longint; var datatype: MPI_Datatype); cdecl;
Параметры invec и inoutvec являются указателями на массивы, содержащие len элементов типа datatype. Элементы массивов invec[i] и inoutvec[i], i = 0, …, len–1, считаются соответственно левым и правым операндом определяемой пользовательской операции; результат применения этой
операции к элементам invec[i] и inoutvec[i] должен сохраняться в элементе
inoutvec[i]. Таким образом, массив invec является входным, а массив inoutvec — одновременно входным и выходным (что и объясняет выбор их
имен).
Если пользовательскую операцию предполагается применять только к
данным фиксированного типа, то при определении пользовательской операции можно считать, что массивы invec и inoutvec имеют требуемый тип,
и не анализировать параметр datatype.
7.2. Функции общего назначения
Функции MPI_Comm_size и MPI_Comm_rank, описанные в данном
пункте, относятся, строго говоря, к категории функций, связанных с группами процессов и коммуникаторами (см. п. 7.8). Тем не менее их можно
считать и функциями общего назначения, поскольку вызов данных функций (для коммуникатора MPI_COMM_WORLD) обычно выполняется в
любом процессе любой содержательной параллельной программы.
int MPI_Init(int* argc, char*** argv);
function MPI_Init(var argc: longint; var argv: PPChar): longint;
INOUT argc
– количество параметров командной строки;
INOUT argv – строковый массив параметров командной строки.
Инициализирует параллельную часть приложения. Параметры передаются по ссылке, поскольку стандарт MPI предусматривает возможность
такой реализации данной функции, при которой передача параметров осуществляется не из параллельной программы в среду MPI, а наоборот: из
среды MPI в параллельную программу.
int MPI_Finalize();
function MPI_Finalize: longint;
Завершает параллельную часть приложения.
int MPI_Comm_size(MPI_Comm comm, int* size);
function MPI_Comm_size(comm: MPI_Comm; var size: longint):
longint;
IN comm
– коммуникатор;
OUT size – число процессов в коммуникаторе.
Определяет общее число параллельных процессов, связанных с указанным коммуникатором.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
