Управление потоками данных в параллельных алгоритмах вычислительной линейной алгебрыНедостатком программ, созданных с помощью данных языков программирования, является их недостаточная переносимость. Кроме того, компиляторы этих языков не всегда входят в стандартный комплект программного обеспечения, поставляемый с компьютером. 2. межпроцессных коммуникаций ( interprocess communication ) такие как разделяемая память ( shared memory ), семафоры ( semaphores ), очереди сообщений ( message queues ), сигналы ( signals ) удобно использовать при программировании в модели разделяемой памяти. При использовнии низкоуровневых средств межроцессных коммуникаций программисту кроме кодирования непосредственно вычислительного алгоритма, требуется самому создавать процедуры синхронизации процессов, что может быть источником дополнительных трудностей. 3. Parsytec , поставляеются со специализированной операционной системой Parix , обеспечивающей реализацию параллельных алгоритмов на программном уровне. ОС Parix предоставляет разработчику библиотеку системных функций, обеспечивающих синхронную и асинхронную передачу данных, получение информации о конфигурации вычислительного узла, на котором запущена программа и т.д. Недостатком таких библиотек является их специализированность , т.е. узкая направленность на конкретную параллельную машину и, как следствие, плохую переносимость. 4. MPI называют ассемблером для параллельных систем). В рамках данной дипломной работы была создана система FLOWer — набор утилит, облегчающих написание параллельных программ. В основе системы лежит модель управления потоком данных. Обычно в вычислительных системах, управляемых потоком данных, команды машинного уровня управляются доступностью данных, проходящих по дугам графа потока данных (ГПД). В данной системе используется принцип управления укрупненным потоком данных ( Large-Grain Data Flow ), в котором единица планирования вычислений — процесс — крупнее (возможно, намного крупнее), чем одна машинная команда. Для задания ГПД был разработан специальный язык DGL ( Dataflow Graph Language ). ГПД, записанный на этом языке, легко настраивается под конкретную многопроцессорную систему — число вершин и дуг графа может определяться через внешние параметры, которые вводятся пользователем, считываются из файла или задавются каким-либо другим способом. В качестве параметров можно использовать число процессоров в системе, степень загруженности системы и т.д. В состав системы FLOWer входят: · · DGL ; · Структура параллельной программы, написанной в системе FLOWer , мало отличается от структуры последовательной программы. Так, процессы записываются ввиде отдельных функций, которые считавают значения параметров из входных дуг ГПД и передают результат в выходные. Использование модели управления потоком данных позволяет избежать сложностей, связанных с синхронизацией. Правда часто это достигается за счет некоторого снижения эффективности программы. Цель данной работы — реализовать ряд алгоритмов вычислительной линейной алгебры в данной модели вычислений, оценить теоретически их эффективность и сравнить полученные результаты с экспериментальными данными. Основные понятия параллелелизма Определение.Степенью параллелизма численного алгоритма называется число его операций, которые можно выполнять параллельно. Определение.Средней степенью параллелизма численного алгоритма называется отношение общего числа операций алгоритма к числу его этапов. Определение.Ускорением параллельного алгоритма называется отношение Параллельный алгоритм называется масштабируемым, если при увеличении числа процессоров производительность также увеличивается. В идеальном случае Определение.Эффективностью параллельного алгоритма называется величина Главные факторы, влияющие на снижение ускорения таковы: · · Определение.Временем подготовки данных называется задержка, вызванная обменами, конфликтами памяти или синхронизацией и необходимая для того, чтобы разместить данные в соответствующих ячейках памяти. Большинство алгоритмов представляют собой смесь фрагментов с тремя различными степенями параллелизма, которые мы будем называть максимальным, частичным и минимальным параллелизмом. Но даже если алгоритм обладает максимальным параллелизмом, ситуация для данной параллельной системы может осложнятся проблемой балансировки нагрузки. Под балансировкой нагрузки понимается такое распределение заданий между процессорами системы, которое позволяет занять каждый процессор полезной работой по возможности большую часть времени. Балансировка нагрузки может осуществляться как статически, так и динамически. Рассмотрим формальную модель системы, в которой Различают несколько специальных случаев этой формулы. Случай 1. SYMBOL 97 f 'Symbol' s 12 a 1 = 0, SYMBOL 97 f 'Symbol' s 12 a 2 = 0, SYMBOL 97 f 'Symbol' s 12 a 3 = 1, t d = 0. Здесь ускорение максимально. Случай 2. SYMBOL 97 f 'Symbol' s 12 a 1 = 0, SYMBOL 97 f 'Symbol' s 12 a 2 = 1, SYMBOL 97 f 'Symbol' s 12 a 3 = 0, t d = 0. Теперь S p = k p . Случай 3. SYMBOL 97 f 'Symbol' s 12 a 1 = SYMBOL 97 f 'Symbol' s 12 a SYMBOL 97 f 'Symbol' s 12 a 2 = 0, SYMBOL 97 f 'Symbol' s 12 a 3 = 1 - SYMBOL 97 f 'Symbol' s 12 a t d = 0. В этом случае Подход к измерению ускорения, который потенциально может учесть обе названные проблемы, состоит в том, чтобы измерять скорость вычислений по мере того, как растут размер задачи и число процессоров. Рассмотрим, например, задачу матрично-векторного умножения Ax . Если An*n-матрица , то потребуется 2n 2 - n операций. Предположим, что при исходном порядке n вычисления на единственном процессоре идут со скоростью 1 MFLOP. Затем мы удваиваем n , и число операций при большом n увеличивается примерно в 4 раза. Если задача решается на 4 процессорах со скоростью 4 MFLOP, то мы достигли максимального ускорения. Вообще, пусть размер задачи определяется параметров n , а число операций есть f ( n ) при растущем n и p = SYMBOL 97 f 'Symbol' s 12 a f ( n ). Если n 1 - размер задачи, посильный для одного процессора, то соответствующий размер задачи n p для системы из p процессоров определяется равенством f ( n p ) = pf (n 1 ) (чтобы число операций, выполняемых p процессорами, в p раз превосходило число операций одного процессора). Определение.Параллельный алгоритм обладает свойством локальности, если он использует локальные данные гораздо чаще, чем удаленные. Наряду с параллелизмом и масштабируемостью это свойство является основным требованием к параллельному програмному обеспечению. Важность этого свойства определяется отношением стоимостей удаленного и локального обращения к памяти. Это отношение может варьироваться от 10:1 до 1000:1 и больше, что зависит от используемой аппаратуры. Метод оценки производительности Задачей программиста является проектирование и реализация программ, которые удовлетворяют требованиям пользователя в смысле производительности и корректной работы. Производительность является достаточно сложным и многосторонним понятием. Кроме времени выполнения программы и масштабируемости следует также анализировать механизмы, отвечающие за генерацию, хранение и передачу данных по сети, оценивать затраты, связанные с проектированием, реализацией, эксплуатацией и сопровождением программного обеспечения. Существуют весьма разнообразные критерии, с помощью которых оценивается производительность. Среди них могут присутствовать: время выполнения программы, ускорение и эффективность, требования по памяти, производительность сети, время задержки при передаче данных ( latency time ), переносимость, масштабируемость , затраты на проектирование, реализацию, отладку, требование к аппаратному обеспечению и т.д. Относительная важность разнообразных критериев будет меняться в зависимости от природы поставленной задачи. Специфика конкретной задачи может требовать высоких показателей для каких-либо определенных критериев, в то время как остальные должны быть оптимизированы или полностью игнорированы. В данной работе основное внимание уделяется ускорению параллельного алгоритма. Для вычисления приближенной оценки производительности алгоритма будем учитывать только наиболее трудоемкие элементарные команды, такие как умножение двух чисел и пересылка данных. Рассмотрим задачу о пересылке n чисел из памяти одного процессора Р 1 в память другого процессора Р 2 . В общем случае такая пересылка реализуется посредством некоторой комбинации аппаратных средств и программного обеспечения и ее стандартный сценарий может выглядеть следующим образом. Прежде всего данные загружаются в буферную память или собираются в последовательных ячейках памяти процессора Р 1 . Затем выполняется команда переслать, результатом которой является перенос данных в буфер или память процессора Р 2 . Далее процессор Р 2 выполняет команду принять, и данные направляются на места своего конечного назначения в памяти Р 2 . Чтобы освободить основные процессоры от значительной части этой работы, можно использовать сопроцессоры. В этом упрощенном описании опущены многие детали (в большей степени зависящие от конкретной системы), но главные пункты сохранены: чтобы переслат данные, их вначале нужно выбрать из памяти передающего процессора, должна быть предоставлена информация, куда следует их послать, должен произойти физический перенос данных от одного процессора к другому и, наконец, данные нужно разместить в надлежащих ячейках памяти принимающего процессора. Для многих систем время такого обмена можно выразить приближенной формулой Подобным образом оценивается время перемножения и сложения n пар чисел. Будем считать, что n пар чисел перемножаются за время nT mul , а складываются за время nT add . При этом не будем различать операции сложения и вычитания, и операции умножения и деления. Экспериментально было установлено, что время T mul на порядок превосходит время T add (конкретное значение зависит от типа процессора и отношение T mul / T add варьируется примерно от 10 до 100). Поэтому часто при оценке времени выполнения алгоритма операции сложения не учитываются. Ч А С Т Ь 1 СИСТЕМА FLOWer В данной части описывается система программирования FLOWer — набор инструментов, в значительной степени облегчающих создание и отладку параллельных программ. Эта система написана на языке Delphi и предназначена для работы в локальных сетях ЭВМ под управлением ОС Windows . Г Л А В А 1 КРАТКИЙ ОБЗОР Программный комплекс FLOWer спроектирован для работы в массивно-параллельной системе ( MPP ), которая состоит из однородных вычислительных узлов, включающих в себя: · · · Узлы связаны через некоторую коммуникационную среду (высокоскоростная сеть, коммутатор и т.п.). На каждом зле работает полноценная ОС (в данном случае Windows ). В частности, такой системой является локальная сеть, в которой любые два компьютера могут обмениваться данными друг с другом. На любом компьютере могут одновременно работать несколько процессов. Данная работа была выполнена в локальной сети с общей шиной. В такой сети все процессоры соединены посредством шины. Достоинством такой системы является очень малое число линий связи, однако возможны задержки (конфликт на шине) при использовании шины несколькими процессорами. Это может стать серьезной проблемой при увеличении числа процессоров. В состав системы FLOWer входят: · · DGL ; · Запуск параллельной программы осуществляется под управлением диспетчера, который распределяет процессы по компьютерам и устанавливает связи между процессами. Для нормальной работы диспетчера на всех компьютерах должна быть запущена специальная программа - монитор. Создание параллельной программы в системе FLOWer состоит из следующих шагов: · · DGL · DGL · · DLL · DGL Г Л А В А 2 МОДЕЛЬ ВЫЧИСЛЕНИЙ Система FLOWer базируется на модели управления потоком данных. В данной модели вычислений программа представляется в виде ГПД. Вершины ГПД соответствуют отдельным процессам — последовательным участкам программы, а дуги задают отношения между ними. Точка вершины, в которую входит дуга, называется входным портом (портом импорта или входом), а точка, из которой она выходит, - выходным (портом экспорта или выходом). Некоторые входные порты могут быть помечены как обязательные. По дугам передаются данные из одного процесса в другой. Основная идея модели управления потоком данных заключается в том, что процесс планируется для исполнения тогда и только тогда, когда во все его обязательные входные порты поступят данные. Т.е. процесс может быть запущен на выполнение, если выполняется одно из следующих условий: · · Введение необязательных входов выводит данную модель за рамки стандартной модели управления потоком данных, но придает системе дополнительную гибкость. Первым запускается на выполнение процесс, помеченный как стартовый. После этого параллельная выполняется до тех пор, пока не завершится процесс, помеченный как завершающий. Программа может включать несколько стартовых и завершающих процессов, причем один и тот же процесс может быть одновременно и стартовым и завершающим. После запуска процесс может взаимодействовать с другими процессами только через каналы. Когда процесс читает данные из входа, его работа приостанавливается до момента поступления данных (предусмотрены функции для асинхронного обмена сообщениями). Входы используются как очереди, и они, подобно каналам в ОС UNIX, буферизуют одно или несколько сообщений до тех пор, пока их не получит адресат. Объем буфера ограничен только доступной емкостью памяти. Каждый вход может быть связан с несколькими выходами. Далее будут рассмотрены структуры данных для записи ГПД. 2.1. ГПД ГПД (Граф Потока Данных) — ориентированный граф, вершинами которого являются процессы, а дугами — каналы. Каждому процессу сопоставлена пара чисел, однозначно определяющая этот процесс, — номер класса процесса и номер экземпляра процесса (о необходимости введения двумерной нумерации процессов будет рассказано несколько позже). Различие между классом и экземпляром процесса такое же, как и в объектно-ориентированных языках программирования. Канал определяет однонаправленный поток данных между процессами, он всегда направлен от входа канала к выходу. Между каналами и выходами имеется взаимооднозначное соответствие; в то же время вход может быть соединен с несколькими выходами. Каждому каналу приписывается вес — величина, характеризующая примерный объем данных, пересылаемых по каналу. Процесс — структура данных, состоящая из набора входов и выходных портов (не путать с выходами). Входы и выходные порты занумерованы. Вход может быть помечен как обязательный. Каждому процессу приписывается вес — величина, характеризующая примерный объем вычислений, выполняемых этим процессом. Выходной порт — массив выходов. Выход — тройка чисел , однозначно определяющая вход, к которому подключен данный выход. Введем систему обозначений. · · Pi — процессы с номером ( i , x ), где x Pi |. · Pij — процесс с номером ( i , j ). · In Pij — множество входов процесса ( i , j ). · In Pij | — число входов процесса ( i , j ). · In k Pij — k-й вход процесса ( i , j ). · Out Pij — множество выходов процесса ( i , j ). · Out k Pij — выходы процесса ( i , j ) с номерами ( k , x ), где x Out k Pij | · Out kl Pij — выход с номером ( k , l ). · Out kl Pij , тогда выход X соединен с входом h = X.in процесса с номером ( s , w ), где s = X.proc , w = X.copy . Т.е. существует канал c = (X, Y), где Y = In h Psw . 2.2. Шаблон ГПД Шаблоны ГПД имеют сходные черты с шаблонами в языке С++. Каждый шаблон ГПД обладает набором параметров, после определения которых из шаблона получается конкретный экземпляр ГПД. От параметров может зависеть число процессов ГПД, число выходов процесса. Параметры шаблона вводятся на этапе запуска программы. Это позволяет настраивать программу под конкретные требования пользователя. Для записи шаблона ГПД был разработан специальный язык DGL ( Dataflow Graph Language ). Более подробно о DGL можно прочитать в главе «Язык DGL ». Шаблон ГПД — это ориентированный граф, вершинами которого являются классы процессов, а дугами — каналы, и набор параметров. Каждому классу процесса сопоставлен номер. Параметры — вектор переменных. Канал определяет однонаправленный поток данных между процессами, он всегда направлен от входа к выходу. Класс процесса — структура данных, состоящая из набора входов и выходов. Входы и выходы занумерованы. Вход может быть помечен как обязательный. Введем систему обозначений. · · Ai — i-й параметр (целое число). · TPi — i-й процесс. · In TPi — множество входов процесса i . · In k TPi — k-й вход процесса i . · Out TPi — множество выходов процесса i . · Out k TPi — k-й выход процесса i . Пусть X = TPi . Тогда · X.ncopies = ncopies (A) — целочисленная функция от параметров, которая задает число копий процесса X. Пусть X = Out k TPi . Тогда · X.ncopies = ncopies ( p , A) — целочисленная функция, которая задает число копий выхода X. Здесь p — целое число, А — параметры. · X.proc — номер процесса, с входом которого соединен данный выход. · X.copy = copy ( c , p , A) — целочисленная функция. Здесь p и c — целые числа, А — параметры. · X.in — номер входа, с которым соединен данный выход. 2.3. Связь ГПД и шаблона ГПД Пусть TG (TP, TC, TA) — шаблон ГПД, A — конкретные значения параметров. Введем операцию подстановки Subst параметров А в шаблон TG. G = Subst A TG — ГПД такой, что · TPi сопоставлено множество процессов Pi . · Pi | = ( TPi ). ncopies (A). · In Pij = In TPi , где j · Out k TPi сопоставлено множество выходов Out k Pij , где j Pi |. · | Out k Pij | = (Out k TPi ). ncopies (j, A), где j · (Out kl Pij ).proc = (Out k TPi ).proc, где l k Pij |, j · (Out kl Pij ).copy = (Out k TPi ).copy (l, j, A), где l k Pij |, j · (Out kl Pij ).in = (Out k TPi ).in, где l k Pij |, j ЗАМЕЧАНИЕ: при некоторых значениях вектора параметров операция подстановки может быть не определена. Г Л А В А 3 ЯЗЫК DGL Язык DGL был специально разработан для описания ГПД. Для ввода програмы на языке DGL можно использовать как простой текстовый редактор, так и специальную программу Rose , которая рисует ГПД на экране компьютера. Рассмотрим как зписываются графы на языке DGL на основе элементарных примеров. 1. Out вершины V 1 связан со входом In вершины V 2 . Синтаксис DGL ::= «DATAFLOW» «PROGRAM» name «;» {«EXTERN» name [«=» integer] «;»} {«CONST» name «=» expression «;»} {process} process ::= «PROCESS» name [«[» number_of_instances «]»] {directive «;»} «{» { process_attr «;»} «EXPORT:» {export} «IMPORT:» {import} «}» directive ::= «LOCAL» | «START» | «TERMINATION» process_attr ::= «weight» «=» integer import ::= name [«{» import_attr {«;» import_attr } «}»] «;» export ::= name [«[» number_of_instances «]»] « --> » process_name [«[» process_index «]»] «:» import_name [«{» export_attr {«;» export_attr } «}»] «;» number_of_instances ::= expression process_index ::= expression import_attr ::= «ARGUMENT» export_attr ::= «DATASIZE» «=» integer Г Л А В А 4 ПРИМЕР ПАРАЛЛЕЛЬНОЙ ПРОГРАММЫ В качестве примера рассмотрим задачу приближенного вычисления числа Пи с использованием правила прямоугольников для вычисления определенного интеграла Существует множество подходов к решению контрольной задачи. Решение, приведенное ниже, иллюстрирует все основные шаги разработки программы. 4.1. Конструирование ГПД программы В пределе разрабатываемая программа может быть создана в виде одного процесса, но при этом теряется параллелелизм . Можно создать множество мелких процессов, таких как один оператор или даже одна арифметическая операция, что приведет к резкому увеличению расходов, связанных с запуском каждого процесса и обменом данных между ними. Следует отметить, что структура решаемой задачи часто наводит на хорошее первое приближение. Рабочие процессы обращаются за очередным заданием к процессу распределения работ. Вся работа не распределяется заранее равномерно между процессами: один рабочий процесс, если он запущен на более быстрой машине, может выполнить львиную долю работы. 4.2. Запись ГПД на языке DGL После того, как граф данных нарисован, каждый процесс, начало и конец каждой дуги помечаются буквенно-цифровым именем, которое используется в языке DGL . Перевод графа потока данных в язык DGL совершается однозначным образом. Каждой вершине ГПД соответствует процесс DGL с тем же именем. Теперь нарисуем ГПД с помощью программы Rose и запишем его на диск в формате DGL . Отдельно будут рассмотрены ленточные и блочно-диагональные матрицы. 1.1. Умножение матрицы на вектор Пусть А – матрица m n , а х — вектор длины n .Тогда произведение можно записать двумя способами Различие способов записи можно рассматривать как различие двух способов доступа к данным, что приводит к разным алгоритмам и для задач матричного умножения и решения линейных систем. Пусть система состоит из р процессоров. Рассмотрим сначала векторно-матричное произведение с помощью линейных комбинаций: Причем синхронизация в данной модели не требуется. Алгоритм скалярных произведений в некоторых отношениях более привлекателен. Пусть p = m , x и a i приписаны процессору i . Каждый процессор выполняет свое скалярное произведение, и при этом паралелизм максимален. Выбор алгоритма вычислений зависит от целого ряда обстоятельств. Матрично-векторное умножение неизбежно является частью более широкого процесса вычислений, и основную роль играет способ хранения матрицы А и вектора х. Еще одно существенное соображение — желаемое расположение результата по окончании умножения: в первом случае результат размещается в памяти одного процессора, тогда как в другом он размещен между процессорами. В реальных системах n и m значительно больше числа процессоров, и каждому процессору передаются несколько строк или столбцов. 1.2. Матричное умножение Аналогично рассматриваются алгоритмы умножения матриц А и В. Пусть матрицы разбиты на блоки Рассмотрим специальные случаи разбиения: · s = 1 — матрица А разбита на группы столбцов; · t = 1 — матрица В разбита на группы строк; · s = t = 1 — алгоритм блочного скалярного произведения; · r = 1 — алгоритм блочного внешнего произведения. Для блочного внешнего произведения распределение блоков по процессорам будет выглядеть следующим образом: Значение p ’ в данном конкретном случае несложно вычислить. Оно находится из уравнения
Очевидно, что А n можно вычислить следующим образом
Заметим, что если полуширина ленты для А равна a , а для В равна b , то полуширина ленты для АВ в общем случае будет равна a + b . Пусть А — матрица размерности n n с полушириной ленты a , В — матрица размерности n n с полушириной ленты a . Причем А разбита на Соответственно, матрицу А выгодно хранить по строкам, а матрицу В — по столбцам. В результате умножения получим матрицу, которая будет храниться в памяти по строкам. На вычисление одного ненулевого элемента матрицы АВ затрачивается время не более (2 a + 1) T mul . Тогда Главный элемент будем выбирать в активном столбце. На k -м шаге процессор, хранящий k - й столбец, выбирает главный элемент, вычисляет значения
Рассмотрим только решение нижнетреугольной системы (решение верхнетреугольной системы организуется аналогичным образом). В качестве алгоритма решения выберем алгоритм скалярных произведений. Его запись на псевдокоде выглядит следующим образом для i = 1 до n для j = 1 до i -1 b i = b i – L ij y j y i = b i / L ii Распараллеливание Пусть вычислительная система состоит из p процессоров, а размерность матрицы L равна n . Разобьем матрицу L на блоки в соответствии с рисунком Оценки производительности Будем считать, что матрица L уже распределена по процессорам. В противном случае выгоднее решать систему последовательным способом. На одном процессоре задача размерности n решается за время Поэтому данный метод редко используется для решения СЛУ, однако он широко используется при вычислении собственных значений. Пусть A — матрица n n . Рассмотрим запись алгоритма на псевдокоде для k = 1 до n -1 Оценки производительности Пусть А — матрица размерности n n . И пусть система состоит из p процессоров, причем n = pm . Распределим матрицу А по процессорам в соответствии со столбцовой циклической схемой хранения. Последовательный алгоритм выполняется за время
Приведем две стандартные теоремы сходимости. Теорема. Если матрица А имеет строгое диагональное преобладание или является неприводимой с диагональным преобладанием, то итерации метода Якоби сходятся при любом начальном приближении х 0 . Теорема. Если матрица A = D – B симметрична и положительно определена, то итерации метода Якоби сходятся при любом начальном приближении х 0 тогда и только тогда, когда матрица D + B положительно определена. Для проверки сходимости итерационных приближений будем использовать следующий критерий: Оценки производительности Для простоты будем считать, что n = pm . Оценим время выполнения одной итерации метода Якоби. |