Параллельные алгоритмы для минимальных остовных деревьев
В теории графов минимальное остовное дерево (MST). графика с и является дерева подграфом который содержит все свои вершины и имеет минимальный вес.
MST — это полезные и универсальные инструменты, используемые в самых разных практических и теоретических областях. Например, компания, желающая поставлять в несколько магазинов определенный продукт с одного склада, может использовать MST, исходящий со склада, для расчета кратчайших путей к каждому магазину компании. В этом случае магазины и склад представляются вершинами, а дорожные соединения между ними - ребрами. На каждом ребре указана длина соответствующего дорожного соединения.
Если не имеет веса по ребрам, каждое остовное дерево имеет одинаковое количество ребер и, следовательно, одинаковый вес. В случае с взвешиванием по ребрам остовное дерево, сумма весов ребер которого наименьшая среди всех остовных деревьев , называется минимальным связующим деревом (MST). Оно не обязательно уникально. В более общем смысле, графы, которые не обязательно связаны , имеют минимальные остовные леса , которые состоят из объединения MST для каждого связного компонента .
Поскольку поиск MST является широко распространенной проблемой в теории графов, существует множество последовательных алгоритмов ее решения. Среди них алгоритмы Прима , Крускала и Борувки , каждый из которых использует разные свойства MST. Все они действуют схожим образом – это подмножество итеративно увеличивается до тех пор, пока не будет обнаружен действительный MST. Однако, поскольку практические проблемы зачастую весьма велики (дорожные сети иногда имеют миллиарды ребер), производительность ключевым фактором является . Одним из вариантов его улучшения является распараллеливание известных алгоритмов MST . [1]
Алгоритм Прима
[ редактировать ]Этот алгоритм использует свойство обрезки MST. Простая реализация псевдокода высокого уровня представлена ниже:
where is a random vertex in repeat times find lightest edge s.t. but return T
Каждое ребро наблюдается ровно дважды — а именно при рассмотрении каждого из его концов. Каждая вершина проверяется ровно один раз, всего помимо выбора самого легкого ребра на каждой итерации цикла. Этот выбор часто выполняется с использованием очереди приоритетов (PQ). Для каждого ребра не более одной операции уменьшенияKey ( амортизируется в ) выполняется, и каждая итерация цикла выполняет одну операцию deleteMin ( ). Таким образом, при использовании кучи Фибоначчи общее время выполнения алгоритма Прима асимптотически составляет .
Важно отметить, что цикл по своей сути является последовательным и не может быть должным образом распараллелен. Это так, поскольку самое легкое ребро с одной конечной точкой в и дальше в может измениться с добавлением ребер к . Таким образом, одновременно невозможно выполнить два выбора самой светлой кромки. Тем не менее, существуют некоторые попытки распараллеливания .
Одна из возможных идей — использовать процессоры для поддержки доступа PQ в на машине EREW-PRAM , [2] тем самым снижая общее время выполнения до .
Алгоритм Краскала
[ редактировать ]Алгоритм MST Крускала использует свойство цикла MST. Представление псевдокода высокого уровня представлено ниже.
forest with every vertex in its own subtree foreach in ascending order of weight if and in different subtrees of return T
Поддеревья хранятся в структурах данных поиска объединения , поэтому проверка того, находятся ли две вершины в одном поддереве, возможна в амортизированных где – обратная функция Аккермана . Таким образом, общее время работы алгоритма составляет . Здесь обозначает однозначную обратную функцию Аккермана, для которой любой реалистичный ввод дает целое число меньше пяти.
Подход 1: Распараллеливание этапа сортировки
[ редактировать ]Как и в алгоритме Прима, в подходе Краскала есть компоненты, которые невозможно распараллелить в его классическом варианте. Например, определение того, находятся ли две вершины в одном и том же поддереве, сложно распараллелить, поскольку две операции объединения могут попытаться соединить одни и те же поддеревья одновременно. На самом деле единственная возможность распараллеливания заключается в этапе сортировки. Поскольку в оптимальном случае сортировка линейна по процессоров, общее время работы может быть сокращено до .
Подход 2: Фильтр-Краскал
[ редактировать ]Другой подход заключался бы в изменении исходного алгоритма путем увеличения более агрессивно. Эту идею высказали Осипов и др. [3] [4] Основная идея Filter-Kruskal состоит в том, чтобы разделить ребра аналогично быстрой сортировке и отфильтровать ребра, соединяющие вершины, принадлежащие одному и тому же дереву, чтобы снизить стоимость сортировки. Представление псевдокода высокого уровня представлено ниже.
filterKruskal(): if KruskalThreshold: return kruskal() pivot = chooseRandom() , partition(, pivot) filterKruskal() filter() filterKruskal() return partition(, pivot): foreach : if weight() pivot: else return (, ) filter(): foreach : if find-set(u) find-set(v): return
Filter-Kruskal лучше подходит для распараллеливания, поскольку сортировка, секционирование и фильтрация интуитивно легко распараллеливаются, когда ребра просто делятся между ядрами.
Алгоритм Блуберри
[ редактировать ]Основная идея алгоритма Борувки — сжатие ребер . Край сокращается при первом удалении из графа, а затем перенаправляя каждое ребро к . Эти новые ребра сохраняют свой старый вес ребер. Если цель состоит не только в определении веса MST, но и в том, какие ребра в него входят, необходимо отметить, между какими парами вершин сжималось ребро. Представление псевдокода высокого уровня представлено ниже.
while for lightest for contract return T
Возможно, что сокращения приводят к образованию нескольких ребер между парой вершин. Интуитивный способ выбора самого легкого из них невозможен в . Однако, если все сокращения, имеющие общую вершину, выполняются параллельно, это выполнимо. Рекурсия останавливается, когда остается только одна вершина, что означает, что алгоритму требуется не более итераций, что приводит к общему времени выполнения в .
Распараллеливание
[ редактировать ]Одно из возможных распараллеливаний этого алгоритма [5] [6] [7] дает полилогарифмическую временную сложность, т.е. и существует константа так что . Здесь обозначает время выполнения графа с края, вершины на машине с процессоры. Основная идея заключается в следующем:
while find lightest incident edges // assign the corresponding subgraph to each vertex // contract each subgraph //
Тогда MST состоит из всех найденных легчайших ребер.
Это распараллеливание использует представление графа массива смежности для . Он состоит из трех массивов - длины для вершин, длины для конечных точек каждого из края и длины для веса ребер. Теперь о вершине другой конец каждого ребра, инцидентного можно найти в записях между и . Вес -е ребро в можно найти в . Тогда -е ребро в находится между вершинами и тогда и только тогда, когда и .
Нахождение самого легкого падающего края
[ редактировать ]Сначала ребра распределяются между каждым из процессоры. -ый процессор получает ребра, хранящиеся между и . Кроме того, каждому процессору необходимо знать, какой вершине принадлежат эти ребра (поскольку сохраняет только одну из конечных точек ребра) и сохраняет ее в массиве . Получить эту информацию можно в с использованием двоичный поиск или в используя линейный поиск. На практике последний подход иногда оказывается быстрее, хотя асимптотически хуже.
Теперь каждый процессор определяет самое легкое ребро, инцидентное каждой из его вершин.
find(, ) for if if
Здесь возникает проблема: некоторые вершины обрабатываются более чем одним процессором. Возможное решение этой проблемы состоит в том, что каждый процессор имеет свой собственный массив, который позже объединяется с остальными с помощью сокращения. Каждый процессор имеет не более двух вершин, которые также обрабатываются другими процессорами, и каждое сокращение находится в . Таким образом, общее время выполнения этого шага составляет .
Присвоение подграфов вершинам
[ редактировать ]Посмотрите на граф, состоящий исключительно из ребер, собранных на предыдущем шаге. Эти ребра направлены от вершины, к которой они относятся самым легким ребром. Полученный граф разлагается на множество слабосвязных компонентов. Цель этого шага — назначить каждой вершине компонент, частью которого она является. Обратите внимание, что каждая вершина имеет ровно одно выходящее ребро, и поэтому каждый компонент представляет собой псевдодерево — дерево с одним дополнительным ребром, которое идет параллельно самому легкому ребру компонента, но в противоположном направлении. Следующий код преобразует это дополнительное ребро в цикл:
parallel forAll if
Теперь каждый слабосвязный компонент представляет собой ориентированное дерево, в корне которого есть цикл . Этот корень выбран в качестве представителя каждого компонента. Следующий код использует удвоение, чтобы назначить каждой вершине ее представителя:
while forAll
Теперь каждый подграф — это звезда . При использовании некоторых передовых методов этот шаг требует время.
Сокращение подграфов
[ редактировать ]На этом этапе каждый подграф сжимается до одной вершины.
number of subgraphs find a bijective function star root
Нахождение биективной функции возможно в используя префиксную сумму. Поскольку теперь у нас есть новый набор вершин и ребер, массив смежности необходимо перестроить, что можно сделать с помощью Integersort на в время.
Сложность
[ редактировать ]Теперь каждая итерация требует время и, как и в последовательном случае, существуют итераций, в результате чего общее время выполнения . Если эффективность алгоритма находится в и это относительно эффективно. Если тогда это абсолютно эффективно.
Дальнейшие алгоритмы
[ редактировать ]Существует множество других параллельных алгоритмов, которые решают задачу поиска MST. При линейном числе процессоров этого можно добиться в . [8] [9] Бадер и Конг представили MST-алгоритм, который на восьми ядрах был в пять раз быстрее оптимального последовательного алгоритма. [10]
Еще одна проблема - это модель внешней памяти - существует алгоритм, предложенный Дементьевым и др. утверждается, что он всего в два-пять раз медленнее, чем алгоритм, использующий только внутреннюю память. [11]
Ссылки
[ редактировать ]- ^ Сандерс; Дитцфельбингер; Мартин; Мельхорн; Курт; Питер (10 июня 2014 г.). Алгоритмы и структуры данных. Основные инструменты . Спрингер Вьюег. ISBN 978-3-642-05472-3 .
- ^ Бродал, Герт Столтинг; Трефф, Йеспер Ларссон; Зарольягис, Христос Д. (1998), «Параллельная очередь приоритетов с операциями постоянного времени», Журнал параллельных и распределенных вычислений , 49 (1): 4–21, CiteSeerX 10.1.1.48.3272 , doi : 10.1006/jpdc.1998.1425
- ^ Осипов, Виталий; Сандерс, Питер; Синглер, Йоханнес (2009), «Алгоритм минимального остовного дерева фильтра-Крусала», Материалы одиннадцатого семинара по разработке алгоритмов и экспериментам (ALENEX). Общество промышленной и прикладной математики : 52–61, CiteSeerX 10.1.1.218.2574
- ^ Сандерс, Питер. «Сценарий разработки алгоритмов» (PDF) . Домашняя страница KIT для разработки алгоритмов . Проверено 25 февраля 2019 г.
- ^ Сандерс, Питер. «Скрипт параллельных алгоритмов» (PDF) . Домашняя страница KIT параллельных алгоритмов . Проверено 25 февраля 2019 г.
- ^ Заде, Реза. «Распределенные алгоритмы и оптимизация» (PDF) . Распределенные алгоритмы и оптимизация. Домашняя страница Стэнфордского университета . Проверено 25 февраля 2019 г.
- ^ Чун, Сунь; Кондон, Энн (1996). «Параллельная реализация алгоритма минимального остовного дерева Бувки». Материалы международной конференции по параллельной обработке . стр. 302–308. дои : 10.1109/IPPS.1996.508073 . ISBN 0-8186-7255-2 . S2CID 12710022 .
- ^ Чонг, Ка Вонг; Хан, Ицзе; Лам, Так Ва (2001), «Параллельные потоки и алгоритм оптимального параллельного минимального остовного дерева», Журнал Ассоциации вычислительной техники , 48 (2): 297–323, CiteSeerX 10.1.1.32.1554 , doi : 10.1145/375827.375847 , Г-Н 1868718 , S2CID 1778676
- ^ Петти, Сет; Рамачандран, Виджая (2002), «Оптимальный параллельный алгоритм с рандомизированной работой по времени для поиска минимального остовного леса» (PDF) , SIAM Journal on Computing , 31 (6): 1879–1895, doi : 10.1137/S0097539700371065 , MR 1954882
- ^ Бадер, Дэвид А .; Конг, Гоцзин (2006), «Быстрые алгоритмы с общей памятью для вычисления минимального остовного леса разреженных графов», Journal of Parallel and Distributed Computing , 66 (11): 1366–1378, doi : 10.1016/j.jpdc.2006.06. 001
- ^ Дементьев Роман; Сандерс, Питер; Шультес, Доминик; Сибейн, Джоп Ф. (2004), «Разработка алгоритма минимального связующего дерева внешней памяти», Proc. IFIP 18-й Всемирный компьютерный конгресс, TC1 3-я Международная конференция по теоретической информатике (TCS2004) (PDF) , стр. 195–208 .