Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Практикум по параллельному программированию с использованием электронного задачника Programming Taskbook for MPI

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
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 в среде Pas­calABC.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] и inout­vec[i], i = 0, …, len–1, считаются соответственно левым и правым операн­дом определяемой пользовательской операции; результат применения этой операции к элементам invec[i] и inoutvec[i] должен сохраняться в элементе
inoutvec[i]. Таким образом, массив invec является входным, а массив inout­vec — одновременно входным и выходным (что и объясняет выбор их
имен).
Если пользовательскую операцию предполагается применять только к данным фиксированного типа, то при определении пользовательской опе­рации можно считать, что массивы 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 – число процессов в коммуникаторе.
Определяет общее число параллельных процессов, связанных с ука­занным коммуникатором.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]