ВВЕДЕНИЕ
Рассматривается технология решения больших систем линейных алгебраических уравнений вида:
Ax = b (1),
где A – невырожденная матрица порядка n*n, b – вектор свободных членов, x – вектор неизвестных. Решение системы осуществляется итерационными методами.
Задача решения систем уравнений вида (1) достаточно распространена. Она возникает при описании нескольких процессов, каждый из которых описывается линейным уравнением. Сюда относится изучение процессов, протекающих в линейных электрических схемах, аппроксимация систем дифференциальных уравнений, в частности, описывающих процессы теплопроводности.
Известно, что при увеличении числа уравнений, входящих в систему, эффективность решения сильно снижается. При этом требуются значительные вычислительные ресурсы и время. Для сохранения эффективности необходимо решать подобные задачи с применением распараллеливания. Это позволяет сократить время, затрачиваемое на решение и снизить требования к составу вычислительных средств.
В начало документа
ЧАСТЬ ПЕРВАЯ. АНАЛИЗ ЗАДАЧИ
Предположим есть некоторый главный процесс. Он принимает исходные данные от пользователя. Далее главный процесс производит их предварительную обработку, преобразуя исходную систему вида (1) в систему вида (2), удобную для итерации. После этого главный процесс создает необходимое число процессов-рабочих, которые и будут решать систему, т.е. каждый процесс решает заданное число уравнений системы (2). Каждому процессу-рабочему пересылаются исходные данные от главного процесса. После чего главный процесс ждет ответы от рабочих. Каждый рабочий выполняет итерацию (или несколько итераций) над своей частью системы и пересылает результат главному процессу. Главный процесс, в свою очередь, ожидает, пока поступят ответы от всех рабочих, затем вычисляет точность решения этой итерации, с целью определения необходимости дальнейших вычислений. Если точность достигнута, то выводится результат, вычисления прекращаются. Если точность не достигнута, то полученные на данном шаге результаты становятся исходными данными для следующей итерации, процесс вычислений аналогично повторяется.
Рисунок 1 – модель распараллеливания задачи.
Описанная модель позволяет наглядно распараллелить вычисления при использовании метода простой итерации. Здесь применен принцип взаимодействия: «Управляющий-рабочие».
Реализация осуществляется с помощью библиотеки классов Gala (автор: С. Гурин, Томск) для среды Delphi. Она предназначена для программирования задач, требующих решения при наличии параллельных процессов и их взаимодействий. При этом, сохраняется удобство работы с параллельными процессами, почти такое же как и при работе со специальными средствами разработки для параллельных вычислений. Библиотека классов Gala распространяется свободно с исходными кодами. Ее можно скачать отсюда: http://gurin.tomsknet.ru/gala.html
В начало документа
ЧАСТЬ ПЕРВАЯ. ПРОГРАММНАЯ РЕАЛИЗАЦИЯ
На рисунке 2 представлена схема программного проекта, реализующего метод простой итерации решения СЛАУ.
В модуле class_lib описаны необходимые структуры данных для организации взаимодействия между процессами. Как описано выше, взаимодействие между процессами осуществляется с помощью сообщений.
В модуле func_lib1 представлены функции, реализующие метод простой итерации, а также функция вычисления ошибки.
В модуле slau_2 описаны функции, реализующие действия главного процесса, действия процессов-производителей, их взаимодействие и контроль получения решения.
Рисунок 2 – модульная структура программы
Здесь же описаны классы TProducer и TMainProcessor, которые являются потомками классов TProducer1 и TMainProcessor1 соответственно, описанных в модуле clas_lib.
Класс TMainProcessor имеет виртуальную процедуру Execute, в которой описаны его действия. Т.о. после создания объекта класса TMainProcess происходит считывание данных с главной формы программы. За это отвечает процедура без параметров
procedure TMainProcessor.FillDataSet; После этого исходные данные преобразуются к виду, удобному для итерации, с помощью процедуры Matrix_To_Iterations
По окончании преобразований, выполняется создание необходимого числа процессов-рабочих. На данном этапе разработки деление исходной матрицы на блоки с последующим решением на одном процессе нескольких уравнений системы не выполняется. Процессов-рабочих создается столько же, сколько и уравнений в исходной системе.
for i := 0 to N-1 do
Prod[i] := TProducer.Create(Group,nil);
После создания процессов формируются сообщения с исходными данными для текущей итерации и присходит отправка сообщений рабочим:
for i := 0 to N-1 do
begin
Messages[i].mA := copy(sA);
Messages[i].vb := copy(sb);
Messages[i].vXk := copy(sXk);
Messages[i].al := al;
Prod[i].Prod_Exch_Channel.Send(Self, Self.Messages[i], INFINITE);
end;
После отправки главный процесс ожидает ответы от рабочих. Это организовано функцией ожидания по каналу
Accept(Main_Exch_Channel);
Когда все рабочие отчитаются, производится анализ необходимости продолжения вычислений – Need_Next_Xk. Если данная функция возвращает True, то наращивается счетчик итераций, переприсваиваются исходные данные и процедура вычисления повторяется с момента формирования и отправки сообщений производителям. В функции Need_Next_Xk используется функция Simple_Error. Она возвращает максимальное значение ошибки на данном шаге. Если это значение превышает необходимую точность, то необходима следующая итерация и Need_Next_Xk возвращает True. Иначе – текущее приближение является результатом решения исходной системы и возвращается False.
Решение системы выводится в журнал обмена данными на главной форме.
Класс TProducer также имеет метод Execute. Но данный метод проще, нежели у главного процесса TMainProcessor. В методе Execute класса TProducer выполняется расчет следующей итерации для одного уравнения исходной системы, т. е. для одного Xi, где i совпадает с номером процесса-рабочего. Т.о. рабочий после создания ожидает поступления исходных данных от главного процесса. Это организовано аналогичным вышеприведенному методом
Accept(Prod_Exch_Channel);
Далее вычисляется следующая итерация:
sNextXk := Simple_Iteration(rA, rb, rXk, N, number);
и готовится сообщение для главного процесса:
Ready_Message.Whose := number;
Ready_Message.Next_Xk := sNextXk;
Готовое сообщение отсылается главному процессу:
MainForm.MainP.Main_Exch_Channel.Send(Self, Self.Ready_Message, INFINITE);
После этого рабочий снова ждет данные для следующей итерации.
Также в модуле slau_2 предусмотрены процедуры для ввода данных из файла и для сохранения в файл введенных вручную в форму данных.
В начало документа
ЧАСТЬ ВТОРАЯ. АНАЛИЗ ЗАДАЧИ
Перевод модели «управляющий-рабочие» на язык COM подразумевает следующее. Управляющий процесс должен быть реализован как COM-клиент, рабочие процессы, выполняющие вычисления, реализуются как COM-серверы, предоставляющие свои услуги через интерфейсы. COM-клиент принимает исходную систему от пользователя, выполняет преобразование к виду, удобному для итерации, делит систему на блоки, рассылает части исходных данных COM-серверам, используя их интерфейсы. Когда ответ получен, клиент выполняет сборку результатов и анализ точности полученного решения. При достижении заданной точности процесс вычислений прекращается. Важно, что в данном случае COM-клиент реализуется как одиночное приложение, использующее услуги нескольких удаленных COM-серверов, что показано на рисунке 3.
Рисунок 3 – модель распределенной системы.
В свою очередь, COM-сервера содержат COM-объекты, которые и реализуют функциональность, обеспечивающую решение систем вида (1) итерационными методами.
Следует отметить, что при такой реализации решение отдельных блоков уравнений исходной системы осуществляется на разных хостах распределенной системы. Это позволяет производить вычисления параллельно и независимо.
В начало документа