|
»» FreePascal »» Lazarus »» MSEide + MSEgui »» Разное »» Книги |
07.12.2005 Илья Аввакумов Распределенные вычисления на FreePascal под Windows.Оглавление
Введение. О чем эта статья.Статья посвящена вопросу написания распределенных (параллельных) вычислений с использованием компилятора FreePascal (использовалась версия 2.0.1) Проблема параллельных вычислений заинтересовала меня совсем не потому что это сейчас модно. Столкнулся с задачей, когда надо было сформировать (для дальнейнего анализа) большой массив данных. Хотелось уменьшить время вычислений имеющимися средствами. Оказывается, организовать параллельные вычисления с использованием моего любимого компилятора — вполне решаемая задача. Стандартом для параллельных приложений для многопроцессорных вычислительных систем де-факто является MPI. Идея MPI-программы такова: параллельная программа представляется в виде множества взаимодействующих (посредством коммуникационных процедур MPI) процессов. Параллельные вычисления требуют
MPI (Message Passing Interface) — стандарт на программный инструментарий для обеспечения связи между ветвями параллельного приложения. В этой статье рассматривается MPICH (MPI CHameleon), свободно распространяемая реализация MPI. Использовалась версия MPICH 1.2.5 для Windows. Установка и настройка MPICH.MPICH для Windows требует
Сразу обговорю, что все примеры тестировались на двух машинах, объединенных в локальную сеть. Один компьютер (сетевое имя ILYA) — мой, а второй (сетевое имя EKATERINA) — жены. Установка.Компьютеры, участвующие в вычислениях, назовем кластером. MPICH должен быть установлен на каждом компьютере в кластере. Для установки нужно
После установки на каждом компьютере должна запуститься служба mpich_mpd (MPICH Daemon (C) 2001 Argonne National Lab). (смотрите рисунок) Если был установлен компонент SDK (что необходимо сделать на том компьютере, откуда будет производиться запуск программ), то в каталоге MPICH (прописанном в пункте szDir) присутствуют подкаталоги SDK и SDK.gcc. Содержимое этих каталогов — библиотечные и заголовочные файлы для языков C, С++ и Fortran. Каталог SDK предназначен для компиляторов MS VC++ 6.x и Compaq Visual Fortran 6.x, а каталог SDK.gcc — для компиляторов gcc и g77. НастройкаНастройку можно осуществить с помощью простых утилит, имеющихся в дистрибутиве. Остановимся подробнее на каталоге mpd\bin в директории MPICH. Содержимое каталога:
Использование команд mpirun и mpiregister ждет нас впереди. Чтобы удостовериться, что службы MPICH, работающие на разных компьютерах, взаимодействуют должным образом, можно воспользоваться утилитой MPIconfig. Для этого следует
Модуль mpi на FreePascal.Все вышеописанное относилось к установке собственно MPICH. Для того, чтобы прикрутить библиотеки MPICH к FreePascal, следует еще немножко поработать.
Cледует воспользоваться динамической библиотекой mpich.dll, которая располагается в системном каталоге (копируется туда при установке MPICH).
Модуль написан с использованием утилиты h2pas.exe и заголовочных файлов *.h из SDK\Include. Простейшая MPI программа на FreePascal.Во именах всех функциях библиотеки MPICH используется префикс Основные функции.Основные функции MPI, с помощью которых можно организовать параллельное вычисление
Утверждается, что этого хватит. Причем первые четыре функции должны вызываться только один раз, а собственно взаимодействие процессов — это последние два пункта. Описание функций, осуществляющих передачу, оставим на потом, а сейчас рассмотрим описание функций инициализации/завершения
function MPI_Init( var argc : longint;
var argv : ppchar) : longint;
Инициализация MPI. Аргументы При успешном вызове функции
function MPI_Comm_size( comm : MPI_Comm;
var nump : longint) : longint;
Определяет число процессов, входящих в коммуникатор
function MPI_Comm_rank( comm : MPI_Comm;
var proc_id : longint) : longint;
Определяется ранг процесса внутри коммуникатора. После вызова этой функции все процессы, запущенные загрузчиком MPI-приложения, получают свой уникальный номер (значение возвращаемой переменной function MPI_Finalize : longint; Завершает работу с MPI. Порядок вызова таков:
Простейшая MPI программа такова. test.pas
uses mpi;
var namelen, numprocs, myid : longint;
processor_name : pchar;
begin
MPI_Init( argc, argv);
MPI_Comm_size( MPI_COMM_WORLD, numprocs);
MPI_Comm_rank( MPI_COMM_WORLD, myid);
GetMem( processor_name, MPI_MAX_PROCESSOR_NAME+1); // константа MPI_MAX_PROCESSOR_NAME равна 256
namelen := MPI_MAX_PROCESSOR_NAME;
MPI_Get_processor_name( processor_name, namelen);
Writeln('Hello from ',myid,' on ', processor_name);
FreeMem(processor_name);
MPI_Finalize;
end.
Здесь, как видно, никакого обмена нет, каждый процесс только "докладывает" свой ранг. Для наглядности выводится также имя компьютера, где запущен каждый процесс. Для его определения используется функция
function MPI_Get_processor_name( proc_name : Pchar;
var name_len : longint) : longint;
При успешном вызове этой функции переменная После компиляции (с соответствующими опциями) >fpc -dRELEASE [-Fu<каталог, где размещен файл mpi.pp>] test.pas должен появиться исполняемый файл test.exe, однако рано радоваться. Запуск этого exe-файла не есть запуск параллельной программы. Запуск MPI-программы.Запуск MPI-программы осуществляется с помощью загрузчика приложения mpirun. Формат вызова таков: >mpirun [ключи mpirun] программа [ключи программы] Вот некоторые из опций команды mpirun:
Для организации параллельного вычисления на нескольких машинах следует
После всех этих действий запуск MPI программы test осуществить можно как >mpirun -pwdfile \\ILYA\COMMON\lgn -hosts 2 ILYA 1 EKATERINA 1 \\ILYA\COMMON\test.exe Изменив соответствующие опции, можно запускать различное число процессов. Например >mpirun -pwdfile \\ILYA\COMMON\lgn -hosts 2 ILYA 3 EKATERINA 3 \\ILYA\COMMON\test.exe На рисунке виден результат такого вызова. Вывод от различных процессов выделяется различным цветом, поскольку опция -nocolor отключена. Обратите внимание на то, что последовательность номер выводимой строки вовсе не совпадает с номером процесса. Этот порядок будет меняться от случая к случаю. На этом рисунке запечатлен Диспетчер задач при запуске на компьютере EKATERINA четырех процессов. Установлен приоритет по умолчанию. Утилита MPIRegister.exe.Поскольку компьютеры ILYA и EKATERINA объединены в локальную сеть, у меня нет никаких проблем с безопасностью. Пароль для пользователя mpiuser хранится в открытом виде в файле lgn. Увы, так можно делать далеко не всегда. Если компьютеры, входящие в кластер, являются частью более разветвленной сети, или, более того, используют подключение к Internet, так поступать не просто не желательно, а недопустимо. В таких случаях следует хранить пароль пользователя, от имени которого будут запускаться процессы, в системном реестре Windows в зашифрованном виде. Для этого предназначена программа MPIRegister.exe. Опции таковы
Запускать mpiregister следует только на главном компьютере. Загрузчик приложения mpirun без опции -pwdfile будет запрашивать данные, сохраненные программой mpiregister. Если таковых не обнаружит, то запросит имя пользователя и пароль сам. Более сложные программы.Сейчас, когда заработала простейшая программа, можно начать осваивать функции обмена данными — именно то, что позволяет осуществить взаимодействие между процессами. Функции двухточечного обмена.Блокирующая передача (прием) — означает, что программа приостанавливает свое выполнение, до тех пор, пока передача (прием) не завершится. Это гарантирует именно тот порядок выполнения операций передачи (приема), который задан в программе. Блокирующая передача осуществляется с помощью функции
function MPI_Send( buf : pointer;
count : longint;
datatype : MPI_Datatype;
destination : longint;
tag : longint;
comm : MPI_Comm) : longint;
Осуществляет передачу
В качестве MPI-типа следует указать один из нижеперечисленных типов. Большинству базовых типов паскаля соответствует свой MPI-тип. Все они перечислены в следующей таблице. Последний столбец указывает на число байт, требуемых для хранения одной переменной соответствующего типа.
Переменная tag — вспомогательная целочисленная переменная. MPI-тип Функция
function MPI_Recv( buf : pointer;
count : longint;
datatype : MPI_Datatype;
source : longint;
tag : longint;
comm : MPI_Comm;
var status : MPI_Status) : longint;
Эта функция осуществляет запрос на получение данных. При ее вызове процесс будет ожидать поступления данных от процесса под номером Число принятых элементов может быть меньше значения переменной Возвращаемая переменная
function MPI_Get_count(var status : MPI_Status;
datatype : MPI_Datatype;
var count : longint) : longint;
Число фактически принятых элементов — в возвращаемой переменной Использование функций двухточечного обмена.В следующем примере вычисление значений элементов массива "разводится" по двум процессам
uses mpi;
const num = 10;
var
teg, numprocs, myid : longint;
i : longint;
status : MPI_Status;
z, x : double;
arr : array[0..num] of double;
function f( x : double) : double;
begin
f := sqr(x);
end;
begin
MPI_Init(argc,argv);
teg := 0;
MPI_Comm_size(MPI_COMM_WORLD, numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, myid);
for i := 0 to num do
case myid of
0:
if i mod 2 = 0 then arr[i] := f(1.0*i)
else
begin
MPI_Recv(@x,1,MPI_DOUBLE,1,teg,MPI_COMM_WORLD,status);
arr[i] := x
end;
1:
if i mod 2 = 1 then
begin
z := f(1.0*i);
MPI_Send(@z,1,MPI_DOUBLE,0,teg,MPI_COMM_WORLD);
end;
end; // case statement
if myid = 0 then for i := 0 to num do writeln(i,' ',arr[i]);
MPI_Finalize;
end.
Формируется массив заданного числа элементов так, что элементы с четными номерами рассчитывает процесс с Улучшить программу, то есть написать такой ее вариант, чтобы использовались все процессы, предоставляю читателю :) Функции коллективного обмена.Коллективный обмен данными затрагивает не два процесса, а все процессы внутри коммуникатора. Простейшими (и наиболее часто используемыми) разновидностями такого вида взаимодействия процессов являются рассылка
function MPI_Bcast( buff : pointer;
count : longint;
datatype : MPI_Datatype;
root : longint;
comm : MPI_Comm) : longint;
Функция
function MPI_Reduce( buf : pointer;
result : pointer;
count : longint;
datatype : MPI_Datatype;
operation : MPI_Op;
root : longint;
comm : MPI_Comm) : longint;
Функция Как и функция Имеется 12 предопределенных операций приведения
Использование коллективных функций ( вычисление числа
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Если у Вас есть материалы для добавления - обращайтесь к авторам проекта. |
| FPC | 2.6.0 | release |
| Lazarus | 0.9.30.4 | release |
| 0.9.31 | ||
| MSE | 2.8.2 | release |