МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования КУБАНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ (ФГБОУ ВПО «КубГУ») Кафедра вычислительных технологий СРАВНИТЕЛЬНЫЙ АНАЛИЗ ТЕХНОЛОГИЙ ПАРАЛЛЕЛЬНОГО ПРОГРАММИРОВАНИЯ ПРИ ИССЛЕДОВАНИИ МИНИМАЛЬНЫХ ДОМИНИРУЮЩИХ МНОЖЕСТВ В МОДЕЛИ КОМПЬЮТЕРНОЙ ADHOC СЕТИ Работу выполнил Д.В. Моисеев Краснодар 2014 СОДЕРЖАНИЕ ВВЕДЕНИЕ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1 Постановка задачи . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.1 Об ad hoc сетях . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2 Анализ требований . . . . . . . . . . . . . . . . . . . . . . . . 8 1.3 Проектирование . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2 Поиск доминирующих множеств . . . . . . . . . . . . . . . . . . 10 2.1 Математическая модель ad hoc сети . . . . . . . . . . . . . . . 10 2.2 Доминирующие множества . . . . . . . . . . . . . . . . . . . . 11 2.3 Задача о наименьшем покрытии . . . . . . . . . . . . . . . . . 13 2.5 Жадный приближенный алгоритм . . . . . . . . . . . . . . . . 14 2.6 Статистическое моделирование . . . . . . . . . . . . . . . . . 16 3 Параллельные вычисления . . . . . . . . . . . . . . . . . . . . . 23 3.1 О параллельном программировании . . . . . . . . . . . . . . . 23 3.2 Параллелизм и многопоточность в C++11 . . . . . . . . . . . . 25 3.3 Использование многопоточности в С++11 . . . . . . . . . . . 26 3.4 Message Passing Interface . . . . . . . . . . . . . . . . . . . . . 28 3.5 Интерфейс OpenMP . . . . . . . . . . . . . . . . . . . . . . . . 31 3.6 Язык гетерогенных вычислений OpenCL . . . . . . . . . . . . 33 3.7 Функциональный язык Erlang . . . . . . . . . . . . . . . . . . 35 3.8 Сравнение технологий . . . . . . . . . . . . . . . . . . . . . . 37 ЗАКЛЮЧЕНИЕ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 СПИСОК ИСПОЛЬЗУЕМЫХ ИСТОЧНИКОВ . . . . . . . . . . . 40 2 ВВЕДЕНИЕ Современные распределенные информационные системы, строящиеся на короткий промежуток времени в определенной местности для решения узко специальных задач(ad hoc сети), находят все более широкое применение. Это, например, задачи по ликвидации последствий чрезвычайных ситуаций, когда группы спасателей, снабженных портативными компьютерами, должны коор динировать свои действия. При этом на основе ad hoc сети разворачивает ся распределенная информационная система, поддерживающая оперативное принятие решений. Эти информационные системы обычно строятся как одноранговые си стемы. Во всех случаях требуется передача в реальном времени большого объема информации между компьютерами ad hoc сети. Управление компью терной сетью усложняется следующими факторами: а) Необходимость экономии электроэнергии портативных устройств приводит к значительному снижению радиуса действия приемо пере дающих блоков. б) Радиус действия снижается также за счет естественных и искусствен ных препятствий, имеющихся на территории. в) Малый радиус действия приводит к риску потери связанности сети и невозможности оперативной передачи информации между компонен тами. г) На фактор связанности влияют также перемещения узлов сети на местности. Топология динамической сети меняется постоянно, управление сетью децентрализованное, поэтому составить заранее и использовать таблицы маршрутизации не представляется возможным. Отдельному узлу не извест на топология всей сети, он обладает только локальной информацией. Коли чество узлов в сети может быть очень большим — многие десятки, сотни и более, что затрудняет поиск маршрута. В связи с этим, некоторые алгоритмы маршрутизации предполагают, что сеть состоит из нескольких взаимосвязан ных доменов. В каждом домене задача маршрутизации решается отдельно, а 3 для удаленных узлов наряду с внутридоменной частью маршрута проклады вается междоменная часть. В математической модели сети появляются задачи разделения большо го связанного графа на подграфы и нахождения доминирующих множеств вершин. Поскольку решать задачи маршрутизации приходится в условиях из меняющейся топологии, делать это нужно быстро. Следовательно возникает задача поиска минимального доминирующего множества, на котором бази руется домен, а также необходимо использовать всю вычислительную мощь устройства для уменьшения времени маршрутизации. Данная проблема поиска минимального доминирующего множества яв ляется актуальной. Если мы знаем такое множество в сети, то задача марш рутизации значительно упрощается и нам легче поддерживать ее работоспо собность. Целью настоящей работы является написание эффективных параллель ных алгоритмов, позволяющих вести исследование минимальных доминиру ющих множеств в модели компьютерной ad hoc сети. Был написан, отлажен и протестирован программный комплекс для проведения статистического мо делирования и проведено исследование мобильных ad hoc систем с помощью этого комплекса. В результате было получено распределение вероятностей относительно количества вершин в минимальном доминирующем множестве для случайного графа, представляющего ad hoc сеть. Для получения этого результата было проделана следующая работа: а) Написана подпрограмма, вычисляющая минимальное доминирующее множество по заданному представлению графа. б) Написана подпрограмма, вычисляющая указанное распределение ве роятностей методом статистического моделирования. в) Написаны параллельные программы, позволяющие быстро и эффек тивно находить минимальное множество. г) Проведено сравнение технологий позволяющих писать параллельные программы. 4 1 Постановка задачи 1.1 Об ad hoc сетях В век коммуникационных устройств, социальных сетей и прочих серви сов, сообщение на расстоянии и мгновенный обмен информацией кажутся чем то само собой разумеющимися. Однако возможность оставаться на связи именно в те моменты, когда коммуникационная инфраструктура оказывает ся нарушенной, приобретает особое значение. Например, на Гаити после ка тастрофического землетрясения главным средством связи оказались спутни ковые телефоны, предоставленные службами помощи. Но парализовать ин фраструктуру сотовой связи могут не только масштабные природные ката клизмы—даже банальное отключение электропитания способны превратить наши мобильные устройства в бесполезные игрушки. В подобных случаях все более привлекательным вариантом становится создание беспроводной самоорганизующейся (или ad hoc) сети. Такая струк тура формирует сама себя всякий раз, когда специально запрограммирован ные устройства связи оказываются в пределах прямого доступа. Каждое из них выполняет в динамической сети функции и передатчика, и приемника, а также, что очень важно, служит ретрансляционным пунктом для всех бли жайших приспособлений. Устройства, расстояние между которыми превыша ет дальность прямой связи, могут поддерживать связь между собой, если им готовы помочь другие приспособления, находящиеся между ними, передавая сообщения по цепочке, как ведра при пожаре. Иными словами, каждый узел в сети служит и коммуникатором для собственных сообщений, и элементом инфраструктуры для сообщений других узлов. Разработка таких сетей ведется уже больше трех десятилетий, но лишь в последние годы успехи теории сетей привели к созданию первых рабо чих крупномасштабных систем. Для того, чтобы подобные сети получили широкое распространение, требуется еще ряд технических прорывов, но на нескольких направлениях успехи уже достигнуты. Беспроводные самоорганизующиеся сети пока еще редко встречаются. Чтобы понять причину их медленного внедрения, полезно рассмотреть раз личия между такими новыми технологиями, как сотовые телефоны и WiFi. 5 Когда вы звоните другу по мобильному телефону, в беспроводной связи за действован только каждый из соединяемых телефонов и ближайшая к нему вышка сотовой связи. Вышки неподвижны и связаны между собой обширной сетью проводов и кабелей. В беспроводных локальных сетях, в частностиWiFi, также используются неподвижные антенны и проводные соединения. Такой подход имеет как достоинства, так и недостатки. Для переда чи информации необходима энергия, и в классических беспроводных сетях она запасается в аккумуляторах мобильных устройств (например, телефонов и ноутбуков), а максимально возможная часть коммуникационной нагруз ки возлагается на стационарную инфраструктуру, питаемую от электросе ти. Ширина беспроводной полосы — также фиксированный и ограниченный ресурс. В традиционных беспроводных сетях ширина полосы экономится за счет передачи большей части информации по проводным каналам. Исполь зование стационарной инфраструктуры позволяет создавать большие и наи более надежные телефонные и WiFi коммуникационные ресурсы в областях, где потребность в них наиболее велика. Однако использование фиксированной инфраструктуры делает эти се ти уязвимыми: их работа нарушается в случае отключения электропитания и других сбоев даже при исправности отдельных телефонов и других мобиль ных устройств в зоне действия сети. Надежность динамических сетей намного выше. Adhoc сети предлага ют уникальные преимущества и универсальность для определенных условий и для определенных приложений. Так как нет фиксированной инфраструк туры, базовых станций, то такие сети могут быть созданы и использоваться в любое время и в любом месте. Adhoc сети могут быть отказоустойчивыми из за того, что их топология не является фиксированной. И действительно, если все узлы мобильны, то состав AdHoc сетей динамически изменяется во вре мени. Добавление и удаление узлов происходит только при взаимодействии с другими узлами, ни одно другое устройство в этом участия не принимает. Если один мобильный прибор отключается, остальные видоизменяют сеть та ким образом, чтобы в возможно большей степени компенсировать выбывший элемент. С подключением и отключением устройств сеть подстраивается и «вылечивается» сама. 6 Но такая перенастройка не дается даром. Сеть должна передавать ин формацию таким образом, чтобы сообщение могло быть реконструировано даже в том случае, если в ходе передачи послания какие то звенья цепи связи между отправителем и адресатом прекратят работу. Система должна опреде лять оптимальный путь доставки сообщения адресату даже при условии, что отправляющее устройство не имеет возможности определить местонахожде ние адресата. Кроме того, сеть должна справляться с неизбежными шумами от множества устройств, одновременно передающих сообщения. На основе ad hoc сети разворачивается распределенная информационная система, поддерживающая оперативное принятие решений. Эти информаци онные системы обычно строятся как одноранговые системы. Во всех случаях требуется передача в реальном времени большого объема информации меж ду компьютерами ad hoc сети. Управление компьютерной сетью усложняется следующими факторами: а) Необходимость экономии электроэнергии портативных устройств приводит к значительному снижению радиуса действия приемо пере дающих блоков. б) Радиус действия снижается также за счет естественных и искусствен ных препятствий, имеющихся на территории. в) Малый радиус действия приводит к риску потери связанности сети и невозможности оперативной передачи информации между компонен тами. г) На фактор связанности влияют также перемещения узлов сети на местности. Топология динамической сети меняется постоянно, управление сетью децентрализованное, поэтому составить заранее и использовать таблицы маршрутизации не представляется возможным. Отдельному узлу не извест на топология всей сети, он обладает только локальной информацией (может быть о своих соседях). Количество узлов в сети может быть очень большим — многие десятки, сотни и более, что затрудняет поиск маршрута. В связи с этим, некоторые алгоритмы маршрутизации предполагают, что сеть состоит из нескольких взаимосвязанных доменов (т.е вводят иерархию в одноуровне7 вую сеть). В каждом домене задача маршрутизации решается отдельно, а для удаленных узлов наряду с внутридоменной частью маршрута прокладывается междоменная часть. 1.2 Анализ требований Прежде чем приступить к проектированию и кодированию программы, необходимо определиться с требованиями к этой программе. Без этого по лучить результат эффективно и быстро не удастся. Итак, рассмотрим нашу задачу. Необходимо написать программный комплекс для проведения исследо ваний мобильных ad hoc систем с помощью этого комплекса. Для получения результата нужно: а) Определиться с представлением графа. б) Написать программу, вычисляющую минимальное доминирующее множество по заданному представлению графа. в) Написать программу, генерирующую графы для случайных ad hoc се тей. г) Написать программу, вычисляющую указанное распределение вероят ностей методом статистического моделирования. д) Провести статистическое моделирование. Также важным требованием является эффективность программного ко да, соблюдение стандартов. Еще одним требованием к программному ком плексу стало время работы. Из за высокого количества вершин задачу невоз можно решать перебором, поэтому был произведен поиск эффективного ал горитма, который справляется с своей задачей намного быстрее. 1.3 Проектирование В качестве основного языка программирования используется С++. Это достаточно мощный язык программирования, содержащий средства создания эффективных программ практически любого назначения — от низкоуровне вых утилит и драйверов до сложных программных комплексов различного назначения. Основным фактором, повлиявшим на выбор, является высокая 8 эффективность С++. Также отдельно был рассмотрен функциональный язык программирования Erlang, позволяющий писать программы в декларативном стиле. Для облегчения процесса кодирования задача была разбита на функции. Сначала главный процесс приложения собирает необходимые данные: тип по верхности, ее размеры, необходимое количество испытаний. Затем выполня ется функция simulate() которая проводит статистическое моделирование следующим образом: а) Генерируются N вершин в геометрическом графе GG по методу, опи санному в [2] б) Геометрический граф GG преобразовывается в обыкновенный граф G, представленный матрицей смежности в) Для графа G определяется наименьшее доминирующее множество вершин и его размер [G] г) Определяются необходимые характеристики д) Процесс повторяется N раз После чего мы получаем и обрабатываем необходимые характеристики. Поскольку координаты узлов в сети случайны, то случайным будет и коли чество вершин в минимальном доминирующем множестве графа G. Таким образом, мы получаем случайный граф сети. Важными оценками размера наи меньшего доминирующего множества являются следующие характеристики: математическое ожидание, дисперсия и функция распределения вероятно стей. Упомянутые характеристики изучались для областей S разной формы: квадратной области, круговой области, прямоугольной области (с различным соотношением сторон), но одной и той же площади. 9 2 Поиск доминирующих множеств 2.1 Математическая модель ad hoc сети В составе алгоритмов управления ad hoc сетью должны присутствовать алгоритмы контроля связанности, а в случае мобильных сетей и алгоритмы предсказывания характеристик графа сети. В качестве математической моде ли ad hoc сети может рассматриваться геометрический граф — математиче ская конструкция, сочетающая в себе графовые элементы и геометрические характеристики. Определим статический геометрический граф как набор GG = fV;P;r;Sg (1) где V — множество вершин, P — отображение P : V ! R3, r — радиус дей ствия приемо передатчика, S ограниченная поверхность, на которой рас полагаются вершины. В этом определении мы считаем, что все компьютеры сети имеют одинаковые характеристики приемо передатчиков. Геометрический граф GG порождает обыкновенный граф G = fV;Eg следующим образом: вершины vi и vj смежны, т.е (vi;vj) 2 E, если длина отрезка между точками P(vi) и P(vj) не превышает величины r, и никакая часть этого отрезка не проходит «под» поверхностью S. Имеющийся обыкновенный граф позволяет известными методами разра батывать алгоритмы маршрутизации в сети и решать другие задачи управле ния сетью. В математической модели сети появляются задачи разделения большого связанного графа на подграфы и нахождения доминирующих множеств вер шин. Доминирующее множество подмножество множества вершин графа та кое, что любая вершина или входит в это подмножество или смежна с одной из вершин этого множества. Поскольку решать задачи маршрутизации прихо дится в условиях изменяющейся топологии, делать это нужно быстро. Следо вательно возникает задача поиска минимального доминирующего множества, на котором базируется домен. Топология сети заранее не предсказуема, поэтому будем считать ее слу чайной. Иными словами, генерируется случайный геометрический граф сети 10 с определенным количеством узлов n в определенной области S, и мы хо тим выяснить его основные характеристики. Поскольку граф случайный, то и его характеристики случайны. Любое доминирующее множество в том чис ле минимальное доминирующее множество — случайное множество вершин. С точки зрения маршрутизации важно знать, сколько(m) там вершин. Но m — тоже случайное число, и мы можем интересоваться его характеристика ми: среднее значение, дисперсия, функция распределения вероятностей. При большом количестве вершин в графе нужно использовать метод статистиче ского моделирования: генерируем N случайных графов с n вершинами, для каждого находим значение m и статистическими методами оцениваем сред нее, дисперсию и т.д. Для получения устойчивых оценок величина N должна быть достаточно большой. По определению геометрического графа (1) мы считаем, что все компью теры в сети имеют одинаковые характеристики приемо передатчиков. Будем полагать, что S не является выпуклой (даже локально). Отображение P кон струируется следующим образом: на поверхности S задано двумерное рас пределение вероятностей A(x;y). Исходя из определения A(x;y) выбирается независимо n точек на S, являющихся координатами компьютеров ad hoc се ти. Компьютерная модель геометрического графа представляет собой мас сив вершин, имеющих координаты на выбранной области. Поверхности S представляют собой классы фигур. Создается основной класс shape. От него наследуются классы circle и rectangle. От класса rectangle идет класс пото мок square. В итоге получаем иерархию классов, диаграмма которой отоб ражена на рисунке 1. Примем радиус приемо передатчиков равным единице. Для исследований использовался метод генерации случайных графов по добно [2]. Для дальнейшей работы необходимо преобразовать геометриче ский граф в обыкновенный, представленный матрицей смежности. Вершины vi и vj смежны, если p (xi .. xj)2 + (yi .. yj)2 <= r 2.2 Доминирующие множества 11 Рисунок 1—Диаграмма наследования Для графа G = fV;Eg доминирующее множество вершин (называемое также внешне устойчивым множеством) есть множество вершин S E, вы бранное так, что для каждой вершины xj , не входящей в S, существует дуга, идущая из некоторой вершины множества S в вершину xj . Таким образом, S есть доминирующее множество вершин, если S [ E(S) = V (2) Для графа, приведенного на рисунке 2 множества вершин f1;2;3;4;5;6;7g, f1;3;5;6g, f1;3;4;7g, f5;6g являются доминирующими множествами. Домини рующее множество является минимальным, если нет другого доминирующего множества, содержащегося в нем. [12] Или, другими словами, множество S называется минимальным домини рующим, если оно удовлетворяет соотношению (2) и нет собственного под множества в S, которое удовлетворяет аналогичному условию (2). Так, на пример, для графа, приведенного на рисунке 2 множество f5;6g—минималь ное, а f2;3;4;7g — нет. Минимальным доминирующим множеством является также множество f4;2;7g, и еще существует несколько таких множеств в этом графе. Следовательно, в графе может быть несколько минимальных домини12 Рисунок 2—Пример графа рующих множеств, и они не обязательно содержат одинаковое количество вершин. Если P — семейство всех минимальных доминирующих множеств гра фа, то число [G] = minjSj (3) называется числом доминирования графа G, а множество S, на котором до стигается минимум, называется наименьшим доминирующим множеством. Для графа, приведенного на рисунке 2, наименьшим доминирующим множеством является множество f5;6g и, следовательно, [G] = 2. 2.3 Задача о наименьшем покрытии Пусть AT — транспонированная матрица смежности графа G с единич ными диагональными элементами. Задача определения наименьшего домини рующего множества графа G сводится к задаче нахождения такого наимень шего множества столбцов в матрице AT, что каждая строка матрицы содер жит единицу хотя бы в одном из выбранных столбцов[11, С. 53]. Эта задача о поиске наименьшего множества столбцов, «покрывающих» все строки, изу чалась довольно интенсивно под названием задачи о наименьшем покрытии (ЗНП). Задача о наименьшем покрытии—NP полная задача информатики в об ласти теории графов[9, С. 845]. В следствие этого неизвестны алгоритмы для ее решения за полиномиальное время. Однако существуют алгоритмы, даю щие «приближённое» решение этой задачи за полиномиальное время. Одним из таких алгоритмов является жадный алгоритм для задачи о наименьшем 13 покрытии[9, С. 369]. Даваемое им решение будет хуже оптимального в ло гарифмическое число раз. С ростом размера задачи качество решения ухуд шается, но всё же довольно медленно, поэтому такой подход можно считать полезным. 2.5 Жадный приближенный алгоритм Жадный алгоритм выбирает множества руководствуясь следующим пра вилом: на каждом этапе выбирается множество, покрывающее максимальное число ещё не покрытых элементов. Псевдокод алгоритма: Greedy .. Set .. Cover(U;F ), где U — заданное множество всех элементов, F — семейство подмножеств U а) X U б) C ? в) while X 6= ? do 1) выбираем S 2 F с наибольшим j X \ S j 2) X X n S 3) C C [ fSg г) return C Но такой алгоритм работает не для всех графов, например для графа на рисунке 2 результатом будет f2;4;7g, а на самом деле наименьшее доминиру ющее множество это f5;6g. Как было показано ранее, поиск минимального доминирующего множе ства сводится к задаче о наименьшем покрытии. Приведем пример для гра фа на рисунке 3. Найдем наименьшее доминирующее множество. Попытаем ся применить жадный алгоритм, описанный выше. Получим f1;4;5g. Но, на сколько мы видим, это неправильный результат. Поэтому изменим алгоритм подобно [12]: а) Заполним множество S именами вершин 14 Рисунок 3—Пример графа б) Заполним массив, с размерностью равной количеству вершин, степе нями вершин. Отсортируем его. в) Нам необходимо обойти все вершины в порядке возрастания их сте пеней. Множество S всех вершин является доминирующим. Для всех вершин, в порядке возрастания их степеней: 1) Удаляем вершину из множества S 2) Если S осталось доминирующим—переходим к следующей вер шине 3) Иначе—добавляем вершину обратно и переходим к следующей вершине г) Полученное таким образом множество S — является наименьшим доминирующим.[12] Сложность этого алгоритма уже в разы меньше и приблизительно равна O(n log n). Рассмотрим граф, изображенный на рисунке 3, и попытаемся применить эти инструкции. Матрицей смежности, с единичными диагональными элементами, для этого графа является A = 0 BBBBBBB@ 11100 11010 10101 01010 00101 1 CCCCCCCA , 15 аh= 0 BBBBBBB@ 12 22 32 41 51 1 CCCCCCCA и hs = 0 BBBBBBB@ 41 51 12 22 32 1 CCCCCCCA — массив степеней вершин и отсортированный массив степеней соответственно. Множество S будет состоять из f1;2;3;4;5g. Теперь, обходя массив hs по очереди пытаемся удалить вершины из множе ства, сохраняя множество S доминирующим. В результате получим наимень шее доминирующее множество S = f2;3g. Рассмотрим компьютерную реализацию. Класс domset, при создании, за полняет матрицу смежности и создает необходимые структуры. При вызове метода calculate происходит заполнение степенями вершин массива hs, пред ставленного в виде дерева. Метод count определяет степень следующим об разом: считает количество единиц в i м столбце матрицы А и вычитает едини цу. Далее, обходом дерева, пытаемся удалить вершину из множества. Метод canDel определяет возможность удаления i й вершины следующим образом: удаление возможно, если для каждой единицы в i м столбце найдется дру гой столбец, содержащий единицу в этой же строке. И этот столбец должен входить в множество S. Таким образом легко получаем наименьшее домини рующее множество. 2.6 Статистическое моделирование Далеко не всегда можно построить аналитическую модель, как функцио нальную зависимость выходного параметра системы от входных параметров. В этих случаях пользуются построением статистических моделей. Методами Монте Карло обычно называют методы решения всевозможных задач, осно ванные по моделированию случайных величин на ЭВМ. Задачи статистиче ского моделирования состоят в том, чтобы, используя ЭВМ воспроизводить поведение статистических моделей, устанавливая связь алгоритмов модели рования с алгоритмами решения задач вычислительной математики с помо щью метода Монте Карло и на этой основе строить удобные в вычислитель ном отношении модели, позволяющие получать необходимые характеристи ки объекта. 16 Сущность метода Монте Карло можно описать следующим образом: производится «розыгрыш»—моделирование случайного явления с помощью некоторой процедуры, дающей случайный результат. Проводя «розыгрыш» много раз, мы получаем статистический материал — множество реализаций случайного явления, который можно обработать обычными методами стати стики. Часто этот прием оказывается проще, чем попытки построить анали тическую модель явления и исследовать зависимость между его параметрами на этой модели. Однако он оправдан только в том случае, если его использо вание проще аналитического. Сущность самого метода статистического моделирования сводится к по строению для процесса функционирования исследуемой системы некоторого моделирующего алгоритма с использованием метода Монте Карло. Данный алгоритм имитирует поведение и взаимодействие элементов системы с уче том случайных входных воздействий и воздействий внешней среды. Рассматриваются две области применения метода статистического мо делирования: а) Для изучения стохастических систем б) Для решения детерминированных задач При решении детерминированных задач основная идея заключается в за мене детерминированной задачи эквивалентной схемой некоторой стохасти ческой системы, выходные характеристики которой совпадали бы с резуль татами решения детерминированной задачи. Естественно, при замене получа ется приближенное решение. Погрешность уменьшается с увеличением числа испытаний.[8] В результате статистического моделирования получается серия частных значений искомых величин или функций, статистическая обработка которых позволяет получить сведения о поведении реального объекта или процесса в произвольные моменты времени: допустим, необходимо вычислить матема тическое ожидание случайных величин , подчиняющихся некоторому закону распределения. Для этого реализуют датчик случайных чисел, имеющий дан17 ное распределение и определяют оценку математического ожидания: M(x) = NP i=1 Xi N (4) Дисперсии[10] D(x) = NP i=1 (Xi ..M(x))2 N .. 1 (5) Функции распределения в таком случае строят эмпирически. Пусть из вестно статистическое распределение частот количественного признака Х. Введем обозначения: nх —число наблюдений, при которых наблюдалось зна чение признака меньшее x1, n – общее число наблюдений (объем выборки). Ясно, что относительная частота события Хх=n. Если х будет изменяться, то, вообще говоря, будет, меняться и относительная частота, т.е. относительная частота nх=n есть функция от х. Так как эта функция находится эмпириче ским (опытным) путем, то ее называют эмпирической. Эмпирической функцией распределения (функцией распределения вы борки) называют функцию F(x), определяющую для каждого значения х от носительную частоту события Х: F(x) = nх=n (6) где nх — число вариант, меньшее х, n – объем выборки Таким образом, для того, чтобы найти, например F(x2), надо число ва риант, меньшее x2, разделить на объем выборки n: F(x2) = nх2=n Из определения функции F(x) вытекают следующие ее свойства: а) Значения эмпирической функции принадлежат отрезку [0;1] б) F(x) — неубывающая функция в) Если х1 — наименьшая варианта, то F(x) = 0 при х 6 х1; если хk –– наибольшая варианта, то F(x) = 1 при х > хk. Если N достаточно велико, то полученные результаты моделирования приобретают статистическую устойчивость и с достаточной точностью мо гут быть приняты в качестве оценок искомых характеристик. Таким образом, независимо от природы объекта исследования (статистической или детерми нированной), подход для решения является общим. Отметим, что при этом 18 не требуется запоминание всего множества генерируемых случайных чисел. Используется только накопленная сумма исходов и общее число реализаций. Это немаловажное обстоятельство вообще является характерным при реали зации имитационных моделей с помощью метода статистического моделиро вания. Как было показано выше, количество вершин в минимальном домини рующем множестве — случайная величина и мы можем интересоваться его характеристиками: среднее значение, дисперсия, функция распределения. В очень простых случаях результат можно получить в виде формулы, но при большом количестве вершин в графе необходимо использовать метод стати стического моделирования: генерируем N случайных графов с n вершинами, для каждого находим значение m — количество вершин в графе и статисти ческими методами оцениваем среднее, дисперсию и все остальное. Для полу чения устойчивых оценок величина N должна быть достаточно большой. Для исследований установим значение N равным 10000. Дальнейшее уве личение количества генерируемых графов не приводит к видимым результа там. Были изучены основные характеристики геометрических графов, отно сящиеся к минимальным доминирующим множествам: математическое ожи дание количества вершин в множестве, дисперсия этого количества и, нако нец, эмпирически была выведена функция распределения вершин в графе. Для исследований использовался метод генерации случайных графов, опи санный в [2]. Упомянутые характеристики изучались для областей S разной формы: квадратной области, круговой области и прямоугольной области(с различ ным соотношением сторон). Вероятности и средние значения оценивались статистическими методами путем генерации случайных геометрических гра фов с заданным распределением вероятностей A(x;y). Во всех случаях ради ус приема передачи отдельного компьютера распределенной системы r = 1. На рисунке 4 приведен график зависимости математического ожидания M(x) количества вершин в минимальном доминирующем множестве от коли чества вершин n в геометрическом графе для квадратной области с длиной ребра b. 19 Рисунок 4—График зависимости математического ожидания от количества вершин в графе График на рисунке 4 показывает не очень быстрое увеличение M(x) для квадратной области S, при b = 2 и практически не увеличивается уже при n > 20. В то же время при b = 10 значение M(x) увеличивается достаточно быстро, но при увеличении n скорость роста замедляется. Для круговой обла сти той же площади ситуация повторяется. Для прямоугольной области той же площади s, с соотношением сторон 1:16, значение площади почти не игра ет роли, при s < 16. При s > 16 зависимость M(x) от площади s значительно увеличивается. Влияние формы области S на M(x) оказывается незначительным. На ри сунке 5 представлены зависимости трех разных форм: квадрата, круга и пря моугольника с различным соотношением сторон. Оказывается, какой бы фор мы не была заданная область, наиболее значимыми факторами будут размер этой области и равномерность распределения узлов сети. Но если область является вытянутой, как например в случае с прямоугольником с соотноше нием сторон 1:16, то математическое ожидание будет выше. Как видно из графика на рисунке 6 дисперсия сначала резко растет, но, при достижении определенного n = k, медленно идет на спад. Например, для b = 2 на промежутке [2; 8] она растет, на [8; 16] медленно, но заметно идет на спад, а при n > 16 понижается настолько медленно, что почти не замет но. При увеличении площади фигуры дисперсия значительно увеличивается 20 Рисунок 5— График зависимости математического ожидания для различных форм областей для того, чтобы начать уменьшаться необходимо гораздо большее количество вершин. Рисунок 6— График зависимости дисперсии от количества вершин в графе График на рисунке 7 показывает нам, что дисперсия количества вершин в минимальном доминирующем множестве почти не зависит от типа области, кроме тех случаев, когда область является вытянутой. В этом случае диспер сия, при достижении определенного n = k, в нашем случае k = 16 начинает заметно расти, относительно областей другой формы. И это вполне логично: чем уже и длиннее область, тем меньше вершин будут связаны при равномер21 ном распределении. А это, в свою очередь, влечет за собой больший разброс и увеличение дисперсии. Рисунок 7— График зависимости дисперсии для различных форм областей 22 3 Параллельные вычисления 3.1 О параллельном программировании Для того чтобы в настоящее время разрабатывать программное обес печение, необходимы практические знания параллельного и распределенно го программирования. Программное обеспечение следует проектировать так, чтобы можно было воспользоваться преимуществами компьютеров, оснащен ных несколькими процессорами. Два события называют одновременными, ес ли они происходят в течение одного и того же временного интервала. Если несколько задач выполняются в течение одного и того же временного интер вала, то говорят, что они выполняются параллельно[15, C. 23]. Причем тер мин параллельно необязательно означает "точно в один момент". Например, две задачи могут выполняться параллельно в течение одной и той же секун ды, но при этом каждая из них выполняется в различные доли этой секунды. Так, первая задача может отработать в первую десятую часть секунды и при остановиться, затем вторая может отработать в следующую десятую часть секунды и приостановиться, после чего первая задача может возобновить вы полнение в течение третьей доли секунды, и т.д. Таким образом, эти задачи могут выполняться по очереди, но поскольку продолжительность секунды с точки зрения человека весьма коротка, то кажется, что они выполняются одновременно. Цель технологий параллелизма—обеспечить условия, позво ляющие компьютерным программам делать больший объем работы за тот же интервал времени. Иногда к параллельности прибегают, чтобы увеличить быстродействие программы или приблизить момент ее завершения. В других случаях парал лельность используется для увеличения продуктивности программы (объема выполняемой ею работы) за тот же период времени при вторичности скорости ее работы. Например, для некоторых Web сайтов важно как можно дольше удерживать пользователей. Поэтому здесь имеет значение не то, насколько быстро будет происходить подключение (регистрация) и отключение пользо вателей, а сколько пользователей сможет этот сайт обслуживать одновремен но. Следовательно, цель проектирования программного обеспечения такого 23 сайта — обрабатывать максимальное количество подключений за как можно больший промежуток времени. Первый способ распараллелить приложение — разбить его на на несколько однопоточных одновременно выполняемых процессов. Процесс— это некоторая единица работы, создаваемая операционной системой. Имен но так обычно происходит, когда запускаются вместе браузер и текстовый процессор. Затем эти отдельные процессы могут обмениваться сообщениями, применяя стандартные каналы межпроцессной коммунникации(сигналы, со кеты, файлы). Недостаток такой организации связи между процессами в его сложности и медленности. Операционная система должна обеспечить защиту процессов так, чтобы ни один из них не смог изменить данные принадлежащие другому. Еще одним недостатком являются неустранимые накладные расхо ды на запуск нескольких процессов, т.к. для запуска процесса требуется вре мя, операционная система должна выделить под него ресурсы. Но благодаря надежной защите процессов, реализованной в операционной системе написать безопасный паралелльный код проще когда имеешь дело с процессами. Дру гим достоинством этого подхода это возможность запуска процессов на раз ных машинах, объединенных сетью. Хотя затраты на коммуникацию возрас тают, но если приложение хорошо спроектированно, то такой способ может оказаться очень эффективным. Альтернативный подход к организации параллелизма это запуск нескольких потоков в одном процессе. Под потоком подразумевается часть выполняемого кода в процессе, которая может быть регламентированна определенным образом. Затраты вычислительных ресурсов на создание по тока, его поддержкой и управлением значительно ниже по сравнению с ана логичными затратами для процессов. Каждый поток имеет свою последова тельность инструкций, выполняется независимо от других и все они вместе —паралелльно. Все потоки процесса существуют в одном и том же адресном пространстве и имеют прямой доступ к глобальным данным, но каждый по ток имеет собственные программный указатель, набор регистров, состояние и стек. Однако за гибкость разделяемой памяти приходится расплачиваться — если к некоторому элементу данных обращаются несколько потоков, то 24 необходимо обеспечить согласованность этого представления во всех пото ках. 3.2 Параллелизм и многопоточность в C++11 Стандартизованная поддержка параллелизма за счет многопоточности — вещь новая для С++. Только новый стандарт С++11 позволит писать мно гопоточный код, не прибегая к платформенно зависимым решениям. Стан дарт 1998 года не признавал существования потоков, а также не была фор мально определена модель памяти, поэтому без сторонних решений писать многопоточные приложения было невозможно и производители компилято ров были вынуждены добавалять различные API для поддержки потоков, на пример, в стандарте POSIX C и в Microsoft Windows API. Все изменилось с выходом стандарта С++11. В нем определена совершен но новая модель памяти с поддержкой многопоточности, а также в стандарт ную библиотеку С++ были включены классы для управления потоками, защи ты разделяемых данных, синхронизации между потоками и низкоуровневых атомарных операций [13]. В основу новой библиотеки многопоточности по ложен опыт использования сторонних библиотек. Например, моделью новой библиотеки стала библиотека Boost Thread Library. Также в новом стандарте в сам язык внесено много изменений, призванных упростить программирова ние и помочь использовать библиотеку многопоточности. Прямая языковая поддержка атомарных операций позволяет писать эффективный код с четко определенной семантикой, не прибегая к языку ассемблера для конкретной платформы. Теперь стало намного проще писать переносимый код—компи лятор сам учитывает особенности платформы, а также учитывает семантику программы, а следовательно создает более оптимизированную программу в целом. Одной из важных проблем, с которой сталкиваются разработчики вы сокопроизводительных приложений, это эффективность. Если необходимо достижение максимальной производительности, то необходимо понимать, что использование высокоуровневых механизмов вместо низкоуровневых средств влечет за собой некоторые издержки. 25 Комитет по стандартизации С++ это понимал, когда проектировал стан дартную библиотеку С++ вообще и библиотеку многопоточности в частно сти. Среди целей проектирования была такая: выигрыш от использования низкоуровневых средств по сравнению с высокоуровневой оберткой должен быть ничтожен или отсутствовать вовсе[4]. Также комитет поставил и дру гую цель—обеспечить достаточное количество низкоуровневых средств для желающих работать на низком уровне, чтобы использовать машину макси мально эффективно. Поэтому наряду с моделью памяти включена библиоте ка атомарных операций для прямого управления на уровне байтов и битов, а также средства межпоточной синхронизации и обеспечения видимости лю бых изменений. Атомарные типы и операции теперь можно использовать в тех местах, где раньше разработчики были вынуждены опускаться на уровень языка ассемблера для конкретной платформы[3, С. 1069]. Таким образом, код с применением новых стандартных типов получается более переносимым и удобным для сопровождения. В некоторых случаях высокоуровневые средства обеспечивают большую функциональность, чем необходимо для конкретной задачи. И обычно это не страшно, но иногда бывает, что избыточная функциональность негативно ска зывается на производительности других частей программы. В таких случаях имеет смысл вручную запрограммировать необходимую функциональность, пользуясь низкоуровневыми средствами. Но дополнительная сложность и возможность внести ошибки намного перевешивают небольшой выигрыш в производители. В тех случаях, когда стандартная библиотека не обеспечива ет необходимой производительности или поведения, может возникнуть необ ходимость в использовании платформенно зависимых средств. Чтобы получить доступ к этим средствам, не отказываясь от стандарт ной библиотеки, типы, имеющиеся в библиотеке многопоточности, иногда содержат в себе функцию native_handle(), которая позволяет работать на уровне платформенного API[3, С. 1101]. 3.3 Использование многопоточности в С++11 Прежде, чем перейти к рассмотрению написанной программы, необхо димо рассмотреть создание потоков и синхронизацию данных. В самом нача26 ле подключается библиотека thread, в которой помещены функции и клас сы для управления потоками, и настраивается соответствующим образом проект. Далее, код, выполняемый паралелльно, необходимо поместить в от дельную функцию. Это объясняется тем, что в каждом потоке должна быть начальнаяфункция, в которой начинается исполнение потока. Для первого потока в приложении таковой является функция main(), а для всех осталь ных задается в конструкторе объекта std : thread. Листинг 1— Пример создания потока 1 # i n c l u d e < i o s t r e am > 2#include<thread> 3 vo id f un c ( ) 4{ 5 s t d : : c o u t << "New t h r e a d " ; 6} 78 vo id main ( ) 9{ 10 s t d : : t h r e a d t ( f u nc ) ; 11 t . j o i n ( ) ; 12 } Как видно из листинга 1, для запуска созданного потока необходимо со здать экземпляр класса thread. Но после запуска нового, начальный поток продолжает работать и иногда возникает необходимость дождаться заверше ния работы нового потока. Для этого вызывается функция join(). Зачастую необходимо выполнять синхронизацию данных в разделяемой памяти. Для этого используют мьютекс и блокировку на мьютекс. Мьютекс — базовый элемент синхронизации в С++11 и описан в заголовочном файле < mutex >. Класс mutex обеспечивает базовые функции lock() и unlock(), которые позволяют синхронизировать доступ к переменным в разделяемой памяти. Перейдем к распараллеливанию программного комплекса. Так как про водится статистическое моделирование и время моделирования одного слу чайного явления достаточно мало, то параллелизм на уровне поиска мини мального доминирующего множества будет слабо увеличивать общую произ водительность. Это обуславливается затратами на создание потоков. Поэто му в данном случае будет использоваться параллелизм над задачей и потоки будут считать минимальное доминирующее множество для заданного коли чества вершин определенное количество раз N, где N = количество испытаний количество потоков . 27 Тестирование проходило в области квадратной формы с ребром рав ным 6. Количество испытаний 10000, за 100% берется результат исходной программы. Полученные данные отображены в таблице 1. Проанализиро вав результат, приходим к следующему выводу: однопоточная программа на std :: thread работает немного медленнее своего исходного аналога из за необходимости управления потоками, что влечет за собой дополнительные накладные расходы. Максимальная производительность на четырехядерном процессоре достигается в 4 потока: затраченное время сокращается практи чески в 2,5 раза, что является хорошим показателем. Таблица 1. Результаты тестирования c использованием std::thread Инструмент Затраченное время Процент Исходная программа 155.834c. 100% std::thread, 1 поток 156.977с. 101% std::thread, 4 потока 65.046с. 42% 3.4 Message Passing Interface Наиболее распространенной технологией программирования для пара лелльных компьютеров с распределенной памятью в настоящее время явля ется MPI[7, С. 5]. Основным способом взаимодействия паралелльных процес сов в таких системах является передача сообщений друг другу, что отражено в названии технологии. MPI программа — это множество паралелльных взаимодействующих процессов. Все процессы порождаются один раз, образуя паралелльную часть программы. Каждый процесс работает в своем адресном пространстве и ни каких общих данных в MPI нет. Для взаимодействия процессов можно созда вать группы процессов с общей средой для общения — коммуникатор. При старте программы всегда считается, что все порожденные процессы работа ют в рамках общего коммуникатора под именем MPI_COMM_WORLD. Этот коммуникатор существует всегда и служит для взаимодействия всех запущенных процессов MPI программы. Кроме него при старте программы 28 имеются коммуникаторы MPI_COMM_SELF, содержащий только теку щий процесс и MPI_COMM_NULL не содержащий ни одного процесса. Каждый процесс MPI программы имеет в каждой группе, в которую он входит уникальный номер процесса, который является неотрицательным чис лом. С помощью него и происходит значительная часть взаимодействия про цессов между собой. Таким образом, выделяются два основных атрибута про цесса: коммуникатор и номер в коммуникаторе. Основным способом общения процессов между собой является посылка сообщений. Каждое сообщение имеет несколько атрибутов такие как номер процесса отправителя, номер процесса получателя, индетификатор и т.д. Од ним из важных атрибутов сообщения является его индетификатор. По нему процесс, принимающий сообщение, может различить два пришедших сообще ния. Инициализация паралелльной части программы происходит вызовом функции MPI_Init(int argc;char **argv) и выполняется только один раз. Функция MPI_Finalize() завершает паралелльную часть приложения. Все последующие обращения к процедурам MPI запрещены. Для того, чтобы узнать количество процессов в группе, необходимо воспользоваться функцией MPI_Comm_size(COMM; size), которая в ар гументе size возвращает число паралелльных процессов в коммуникаторе COMM. Процедура MPI_Comm_rank(COMM;rank) в переменную rank возвращает номер процессора в коммуникаторе. Используя операции коллективного взаимодействия процессов проис ходит взаимодействие процессов. Соответствующая процедура должна быть вызвана каждым процессом со своим набором параметров. MPI гарантиру ет, что сообщения, вызванные коллективными функциями никак не повли яют на выполнение других операций. Но нельзя рассчитывать на синхро низацию процессов при помощи этих операций, за исключением процедуры MPI_Barrier(COMM), которая используется для барьерной синхрониза ции. Работа процессов блокируется до тех пор, пока все оставшиеся процес сы из коммуникатора COMM не выполнят эту процедуру. Коллективная процедура MPI_Bcast(*BUF,COUNT,DATATYPE,ROOT,COMM) рассылает COUNT элементов типа DATATY PE из массива BUF 29 от процесса ROOT всем процессам коммуникатора COMM. При воз врате из процедуры содержимое BUF будет скопировано в локаль ный буфер каждого процесса коммуникатора COMM. А процедура MPI_REDUCE(SBUF,RBUF,COUNT,DATATYPE,OP,ROOT,COMM) выполнит COUNT независимых операций OP над соответствующими элементами массива SBUF. Результат выполнения операции помещается в массив RBUF. В MPI предусмотрен ряд предопределенных операций: а) MPI_MAX, MPI_MIN — определение максимального и минимального значения. б) MPI_SUM, MPI_PROD—определение суммы и произведения. в) MPI_MAXLOCK, MPI_MINLOCK — определение максимального и минимального значения и их местоположения. Кроме того, программист может задать свою функцию для выполнения глобальной операции при помощи процедуры MPI_OP_CREATE. При распараллеливании программы, используя MPI, достаточно тяжело синхронизировать процессы на уровне минимального доминирующего мно жества. Распределенная память не позволяет обращаться к памяти других процессов и поэтому намного проще и выгоднее в плане производительно сти считать в каждом процессе минимальное доминирующее множество для заданного количества вершин определенное количество раз. Таким образом синхронизация происходит только в конце последней итерации для конкрет ного числа вершин. Перед запуском статистического моделирования процесс с индетифика тором ’0’ считывает необходимые данные, а затем процедурой MPI_Bcast рассылает эти данные другим процессам. После этого, все запущенные про цессы проводят моделирование и в конце каждой итерации происходит сум мирование в процессе с индетификатором ’0’. По завершении главный про цесс выводит все данные в файл в формате CSV. Тестирование проходило в области квадратной формы с ребром равным 6. Количество испытаний было установлено 10000, за 100% берется резуль тат исходной программы. Полученные данные отображены в таблице 2. Про анализировав результат, приходим к следующему выводу: однопоточная про30 грамма, с использованием MPI, работает не хуже своего исходного аналога, что объясняется эффективно написанным кодом и оптимизацией библиоте ки. Максимальная производительность на четырехядерном процессоре до стигается в 4 потока и, как видно из таблицы 2, приводит к трехкратному уменьшению времени выполнения программы. Таблица 2. Результаты тестирования c использованием MPI Инструмент Затраченное время Процент Исходная программа 155.834c. 100% MPI, 1 поток 156.003с. 100% MPI, 4 потока 50.059с. 32% 3.5 Интерфейс OpenMP Одним из наиболее популярных средств программирования для компи ляторов с разделяемой памятью, в настоящее время является технология OpenMP[6, С. 71]. За ее основу берется последовательная программа, а для создания ее паралелльной версии пользователю предоставляется набор ди ректив, функций и переменных окружения. Одним из главных достоинств является возможность компиляции исходного текста распараллеленной про граммы в системе без поддержки OpenMP—программа компилируется так, как будто в ней отсутствуют эти директивы[6, С. 75]. Основная проблема сегодняшнего паралелльного программирования за ключается в относительной сложности построения схемы паралелльных вы числений в голове программиста. Человек мыслит последовательно и именно поэтому последовательны большинство существующих сегодня языков про граммирования. Но сейчас, когда процессоры перестали наращивать частоту и начали увеличивать количество ядер становится все более актуальным про граммирование паралелльных вычислительных структур. Еще одним важным достоинством технологии OpenMP является воз можность постепенно находить участки в программе, содержащие ресурс па раллелизма, помощью предоставляемых механизмов делать их паралелльны31 ми, а затем переходить к анализу следующих участков. Такой подход зна чительно облегчает процесс адаптации последовательных программ к пара лелльным компьютерам, а также отладку и оптимизацию. Программа начинается с последовательной области—сначала работа ет один поток. При входе в паралелльную область порождается еще некото рое число процессов между которыми в дальнейшем распределяются части кода. По завершении паралелльной области все потоки, кроме первой, завер шаются, и начинается последовательная область[6, С. 77]. В программе мо жет быть любое количество паралелльных и последовательных областей. Для написания эффективной паралелльной программы необходимо равномерно нагрузить все потоки, учавствующие в обработке программы. Существенным моментом является необходимость синхронизации до ступа к общим данным. Наличие общих данных для нескольких потоков при водит к конфликтам при одновременном несогласованном доступе. Поэтому значительная часть функциональности OpenMP предназначена для синхрони зации работающих потоков. Все директивы OpenMP можно разделить на 3 категории: определе ние паралелльной области, распределение работы, синхронизация. Директива parallel задает паралелльную область при этом каждый поток получает свой уникальный идентификатор, а при выходе из паралелльной области происхо дит неявная синхронизация и уничтожение порожденных потоков. Если в паралелльной области встетился оператор цикла, то он будет вы полнен всеми потоками текущей группы, т.е каждый поток выполнит все ите рации данного цикла. Для распределения итераций цикла можно использо вать директиву for. При таком распараллеливании необходимо убедиться в том, что итерации цикла не имеют информационных зависимостей, которые могут привести к неправильной работе программы. Распараллеливание программного комплекса происходило при помощи директивы #pragma omp parallel for reduction(+: d1,d2). Итерации в основном цикле программы распределялись между потоками, а затем полученные дан ные суммировались и вычислялись моменты первого и второго порядка. При тестировании получились данные, отображенные в таблице 3. Результат по32 чти такой же как с использованием std :: thread, но использовать OpenMP на порядок легче. Таблица 3. Результаты тестирования c использованием OpenMP Инструмент Затраченное время Процент Исходная программа 155.834c. 100% OpenMP, 1 поток 155.835с. 100% OpenMP, 4 потока 72.625с. 47% 3.6 Язык гетерогенных вычислений OpenCL Язык OpenCL — единый стандарт для написания приложений, которые должны исполняться в системе, где установлены различные по архитектуре процессоры, ускорители и платы расширения[5, С. 17]. Основным местом, где можно встретить гетерогенные системы, являются высокопроизводительные вычисления: от моделирования физических процессов в пограничном слое до кодирования видео и рендеринга трехмерных сцен. Раньше подобные задачи решали применяя суперкомпьютеры либо очень мощные настольные систе мы. Но с появлением NVidia CUDA/AMD Stream стало возможным писать программы, использующие вычислительные мощности графической системы. Таким образом, появилось множество устройств, на которых можно про изводить паралелльные вычисления и для кадого типа существует свой набор библиотек, свой язык программирования и программная модель. То есть под каждую платформу приходилось разрабатывать свою программу, что очень не удобно. Тогда было решено создать некий единый стандарт для программ, исполняющихся в гетерогенной среде. Это означает, что программа вообще может исполняться на компьютере, в котором одновременно установлены несколько различных устройств, вплоть до исполнения на центральном про цессоре. OpenCL задумывался как технология для создания приложений, кото рые могли бы исполняться в гетерогенной среде. Более того, он разработан так, чтобы обеспечивать комфортную работу с такими устройствами, кото33 рые сейчас находятся только в планах и даже с теми, которые еще никто не придумал. Для координации работы всех этих устройств гетерогенной систе ме всегда есть одно главное устройство, который взаимодействует со всеми остальным посредствами OpenCL API. Такое устройство называется хост, он определяется вне OpenCL. Таким образом, этот язык исходит из наиболее общих предпосылок: су ществует некоторое устройство, которое преполагается использовать для вы числений — в нем есть некий «процессор», то есть нечто, что может испол нять команды. Кроме вычислительных ресурсов устройство имеет какой то объем памяти. И, собственно, все[5, С. 48]. Больше никаких предположений не делается. Такое широкое понятие об устройстве позволяет не накладывать каких либо ограничений на программы, разработанные на OpenCL. Создание приложения довольно нетривиально и состоит из следующих шагов: а) Создание контекста для исполнения программы. б) Выбор необходимого устройствами. в) Инициализация выбранного устройства созданным контекстом. г) Создание очереди команд на основе ID устройства и контеста. д) Сборка программы. е) Создание ядра. ж) Создание объектов памяти для входных и выходных данных. з) Заполнение очереди команд командами записи, чтения данных и ис полнение созданного ядра. и) Ожидание завершения операций. В итоге модель OpenCL получилась универсальной, но при этом она остается низкоуровневой, позволяя оптимизировать приложения под каж дую архитектуру. Также она обеспечивает кросплатформенность при пере ходе от одного типа OpenCL устройств к другому. Кроме того, правильно написанное приложение будет оставаться эффективным при смене поколе ний устройств. OpenCL использовался в программном комплексе на уровне поиска ми нимального доминирующего множества. Каждому процессу в группе отво34 дились определенные номера вершин и процесс сам решал оставлять ли ее в множестве или убрать. Таким образом получилось достаточно быстрое, ис пользующее всю вычислительную мощь компьютера, приложение. Результаты тестирования отображены в таблице 4. Нетрудно заметить, что использование графических ускорителей может сыграть большую роль в производительно сти приложения: время выполнения сократилось больше чем в 12 раз. Таблица 4. Результаты тестирования c использованием OpenCL Инструмент Затраченное время Процент Исходная программа 155.834c. 100% OpenCL, хост 69.371с. 45% OpenCL, AMD 5770 12.541с. 8% 3.7 Функциональный язык Erlang Erlang — функциональный язык предназначенный для создания рас пределенных систем. Включает в себя средства порождения параллельных облегченных процессов и их взаимодействия через обмен асинхронными сообщениями[1, С. 19]. Этот язык был разработан для применения в распре деленных, отказоустойчивых, паралелльных систем. Свой синтаксис и неко торые концепции Erlang унаследовал от языка Пролог. Функциональная пара дигма позволяет избежать многих проблем распределенных приложений как необходимость синхронизации, опасность возникновения тупиков и гонок. Многие авторы публикаций по параллельным вычислениям сходятся в том, что для описания параллельных программм необходимо уйти от импе ративных языков программирования[14, С. 11]. Эти языки описывают какие действия и в каком порядке необходимо выполнить, чтобы получить резуль тат. В данном случае требуется использование декларативных языков, т.е та ких, которые описывают чем является результат, который должен быть по лучен, оставив выполнение действий на компилятор. Однако даже многие де кларативные языки, не смотря на свою мощь, не обеспечивают полноценной 35 базовой платформы для описания паралелльных алгоритмов. Но не Erlang, который задумывался как раз для паралелльных вычислений. Главное в Erlang — это его модель легковесных процессов[1, С. 141]. Создание процесса занимает не больше ресурсов, чем вызов функции, а един ственным способом ваимодействия является асинхронный обмен сообщени ями. Мощность связи «Процессы + сообщения» не меньше, чем «Объекты + интерфейсы + наследование», но зачатую приводит к более компактным и понятным решениям. Отсутствие необходимость блокировки доступа к со сотоянию процесса для синхронизации сильно облегчает жизнь[1, С. 160]. Создание процесса в Erlang весьма тривиально и происходит вызовом функции spawn(Module, Function, List of Arguments). В результате функция вернет идентификатор процесса и обмен сообщениями происходит в формате PID ! message. Причем сообщения Erlang процессов это просто конкретные терминалы. Это могут быть списки, кортежи, целые, атомы, PID и т.д. У каждого процесса есть своя очередь сообщений и новые становятся в конец этой очереди. При обработке процессом сообщений первое в очере ди сообщение сопостовляется с шаблонами и выполняется соответствующее действие. При достижении конца очереди, процесс блокируется и ждет полу чения новых сообщений. Стандартная библиотека Erlang содержит большое количество модулей, а в частности модули для работы с графами: создание, добавление вершин и ребер, поиск пути между вершинами и т.д. Это значительно упрощает перепи сывание программного комплекса на этот язык и проведение статистического моделирования. Полученная программа, будучи написанной в декларативном стиле, становится проще для понимания, проще отлаживается, а ее произво дительность остается на равне с исходной. При написании паралельной программы использовался параллелизм на уровне поиска минимального доминирующего множества. Каждому процессу отводились определенные вершины в графе и процесс самостоятельно решал оставлять ли вершину в доминирующем множестве. Таким образом, главный процесс брал на себя только генерацию исходных данных и обработку полу ченных данных от запущенных процессов. А так как запуск процессов и об36 мен сообщениями достаточно простые операции, то программа получилось высокопроизводительной. Результаты отображены в таблице 5. Таблица 5. Результаты тестирования c использованием Erlang Инструмент Затраченное время Процент Исходная программа 155.834c. 100% Erlang, без процессов 172.126с. 110% Erlang, с процессами 64.312с. 41% 3.8 Сравнение технологий Было рассмотрено 5 различных технологий для осуществления паралле лизма и каждая из них обладает своими достоинствами и недостатками. Рас смотрим сначала сводную таблицу производительности, отображенную ниже. Таблица 6. Сводная таблица тестирования Инструмент Затраченное время Процент Исходная программа 155.834c. 100% OpenCL, AMD 5770 12.541с. 8% MPI 50.059с. 32% Erlang 64.312с. 41% std::thread 65.046с. 42% OpenCL, хост 69.371с. 45% OpenMP 72.625с. 47% Таким образом, самыми эффективными оказалась вычисления на графи ческих процессорах. Прирост в производительности сокращает время выпол нения программы более чем в 12 раз, что является огромным преимуществом. Другим достоинством данной технологии является кросплатформенность на писанного кода. Однако сложность написания такой программы это большой недостаток OpenCL. 37 Среди вычислений на центральном процессоре хорошо себя зарекомен довало использование MPI. Распределенная память позволяет не заботиться об организации общего доступа к данным, а параллелизм на процессах поз воляет добиться лучшей производительности. С другой стороны, запуск та кой программы возможен только через стороннее приложение, что не всегда удобно. Если программа еще на стадии проектирования, то есть смысл реализо вать ее на декларативном, функциональном языке Erlang. Обеспечить парал лелизм достаточно просто, приложение получается эффективным, устойчи вым и простым к сопровождению. Однако необходимо изучать новую пара дигму программирования, что не всегда возможно. Когда программа уже написана, то самыми простыми способами распа раллелить ее это использование std::thread и OpenMP. OpenMP позволяет на ходить участки кода, пригодные для параллельного выполнения и постепенно увеличивать паралелльную часть. Преимуществом такого подхода являются низкие трудовые затраты, но такой способ менее производителен. Преимуще ством std::thread является встроенная на уровне языка поддержка, что позво ляет писать параллельные программы без сторонних библиотек. 38 ЗАКЛЮЧЕНИЕ В процессе написания программного комплекса были изучены основные характеристики компьютерной модели такой информационной системы как ad hoc сети и были получены экспериментальные данные. При исследовании этих данных, мы определили, что количество вершин в минимальном доми нирующем множестве зависит от площади области и почти не зависит от ее формы. Были изучены такие характеристики как математическое ожидание количества вершин в множестве, дисперсия количества, была эмпирически получена функция распределения этого количества. И в ходе исследования установили, что случайные характеристики количества вершин в минималь ном доминирующем множестве зависят, в основном только от количества уз лов в области и от площади этой области. Также были рассмотрены основные технологии для написания парал лельных программ. В ходе исследования были изучены преимущества и недо статки каждого подхода, написаны соответствующие приложения, а также были произведены замеры времени выполнения с точностью до миллисекун ды. В итоге самым быстрым является использование графических процес соров для поиска минимального доминирующего множества. Для рассчета на центральном процессоре необходимо определить требования к написанию программного продукта. Если приложение находится на стадии проектирова ния, то лучшим решением будет осуществить реализацию на функциональном языке Erlang, что облегчит распараллеливание. Если же от программы требу ется производительность, то необходимо воспользоваться технологией MPI. Для написанного продукта выгоднее воспользоваться библиотекой OpenMP или встроенные в язык потоки. 39 СПИСОК ИСПОЛЬЗУЕМЫХ ИСТОЧНИКОВ 1 Amstrong J. Programming Erlang. // USA, 2007. 2 Atay Onat F., Stojmenovic I., Yanikomeroglu H. Generating random graphs for the simulation of wireless ad hoc, actuator, sensor and internet networks. Pervasive and Mobile Computing 4,(2008), // MIT с. 597–615. 3 Becker P. Working Draft, Standard for Programming Language C++. // USA, 2007. 4 Crowl L. Programming Language C++. // MIT, 2005, с. 2. 5 Gaster B.R. Heterogeneous Computing with OpenCL. // Waltham, 2013. 6 Matloff N. Programming on Parallel Machines. // University of California, 2008. 7 Антонов А.С. Параллельное программирование с использованием техно логии MPI. // из во МГУ, 2004. 8 Кибзун А.И., Горяинова Е.Р. Теория вероятностей и математическая ста тистика. Базовый курс с примерами и задачами. Учебн. пособие. // М.: ФИЗМАЛИТ, 2002, с. 168. 9 Кормен Т.Х. Алгоритмы: построение и анализ. // М.: Московского центра непрерывного математического образования, 2001. 10 Костин В.Н., Тишина Н.А. Статистические методы и модели: Учебное пособие. // Оренбург: ГОУ ОГУ, 2004. с. 11–12. 11 Кристофидес Н. Теория графов. Лондон: Изд во Academic Press Inc. // 1977, перевод на русский «Мир», 1978. 12 Майника Э. Алгоритмы оптимизации на сетях и графах. // М.: из тво«Мир», 1981, С. 201–215. 13 Уильямс Э. Параллельное программирование на С++ в действии. // Москва, 2012. с 36. 14 Федотов И.Е. Некоторые приемы параллельного программирования. // Москва, 2008. 15 Хьюз К., Хьюз Т. Параллельное и распределенное программирование на С++. // Москва 2004 г. 40