Хранение очень больших графиков на алгоритмах разбиения диска / потокового графа? - PullRequest
13 голосов
/ 28 января 2010

Предположим, что у меня есть очень большой неориентированный невзвешенный граф (начиная с сотен миллионов вершин, ~ 10 ребер на вершину), не распределенный и обработанный только одним потоком, и что я хочу выполнить поиск в ширину Это. Я ожидаю, что они будут привязаны к вводу / выводу, поэтому мне нужна корректная компоновка страницы диска BFS, дисковое пространство не является проблемой. Поиск может начинаться в каждой вершине с равной вероятностью. Интуитивно это означает минимизацию количества ребер между вершинами на разных страницах диска, что является проблемой разбиения графа.

Сам график выглядит как спагетти, представляющий собой случайный набор точек, случайно связанных между собой, с некоторым смещением в сторону более коротких краев.

Проблема в том, как один граф разделов так велик? Я обнаружил, что доступные разделители графов работают с графами, которые помещаются только в память. Я не смог найти ни описания, ни реализации каких-либо алгоритмов разбиения потокового графа.

ИЛИ, может быть, есть альтернатива разделению графа для получения структуры диска, которая хорошо работает с BFS?

Прямо сейчас в качестве приближения я использую тот факт, что к вершинам привязаны пространственные координаты, и помещаю вершины на диск в порядке сортировки Гильберта. Таким образом, пространственно близкие вершины попадают на одну и ту же страницу, но наличие или отсутствие ребра между ними полностью игнорируется. Могу ли я сделать лучше?

В качестве альтернативы, я могу разбить граф на части, используя порядок сортировки Гильберта для вершин, разделить подграфы, сшить их назад и принять плохое разбиение по швам.

Некоторые вещи, которые я уже изучил:

  1. Как хранить большой ориентированный невзвешенный граф с миллиардами узлов и вершин
  2. http://neo4j.org/ - я обнаружил нулевую информацию о том, как это делает макет графика на диске

Реализация секционирования (если я не ошибаюсь, все они должны помещать граф в память):

  1. http://glaros.dtc.umn.edu/gkhome/views/metis
  2. http://www.sandia.gov/~bahendr/chaco.html
  3. http://staffweb.cms.gre.ac.uk/~c.walshaw/jostle/
  4. http://www.cerfacs.fr/algor/Softs/MESHPART/

РЕДАКТИРОВАТЬ: информация о том, как выглядят графики и что BFS может начинаться везде. РЕДАКТИРОВАТЬ: идея разделения подграфов

Ответы [ 3 ]

3 голосов
/ 29 января 2010

Ни один алгоритм действительно не должен «вписываться в память» - вы всегда можете перемещать объекты по мере необходимости. Но вы не хотите, чтобы вычисление занимало неоправданно много времени - а глобальное разбиение графа в общем случае - это NP-полная проблема, которая «неоправданно длинна» для большинства задач, которые даже не помещаются в память.

К счастью, вы хотите выполнить поиск в ширину, что означает, что вам нужен формат, в котором ширина в первую очередь является простым вычислением. Я не знаю ни одного алгоритма, который бы так делал, но вы можете создать свой собственный макет в ширину, если хотите выделить немного дополнительного дискового пространства.

Если края не смещены в сторону локальных взаимодействий, то распутывание графика будет затруднено. Если они смещены в сторону локальных взаимодействий, то я предлагаю алгоритм, подобный следующему:

  • Выберите случайный набор вершин в качестве отправных точек для всего набора данных.
  • Для каждой вершины собрать все соседние вершины (выполняется один проход по набору данных).
  • Для каждого набора соседних вершин собрать набор соседей и ранжировать их в соответствии с тем, сколько ребер соединяется с ними. Если на странице нет места для их хранения, оставьте наиболее связанные вершины. Если у вас есть место для их сохранения, вы можете отказаться от наименее полезных (например, если доля ребер, находящихся в пределах страницы / фракции вершин, для которых требуется коэффициент хранения, падает «слишком низко» - где «слишком низко») будет зависеть от того, насколько шире ваши поиски, а также от того, сможете ли вы выполнить обрезку и т. д., а затем не включайте их в окрестности.
  • Повторяйте процесс сбора и ранжирования соседей, пока ваше соседство не будет заполнено (например, заполнит какой-то размер страницы, который вам подходит). Затем проверьте повторы среди случайно выбранных запусков. Если у вас есть небольшое количество вершин, появляющихся в обеих, удалите их из одной или другой, в зависимости от того, что ломает меньше ребер. Если у вас есть большое количество вершин, появляющихся в обеих, сохраняйте соседство с наилучшим соотношением (вершины в окрестности / разбитое ребро) и отбрасывайте остальные.

Теперь у вас есть некоторые локальные окрестности, которые являются приблизительно локально оптимальными в этом поиске шириной, как правило, попадают внутрь. Если ваш поиск в ширину довольно эффективно удаляет непродуктивные ветви, то, вероятно, этого достаточно. Если нет, то вы, вероятно, хотите, чтобы соседние районы были объединены.

Если вам не нужны соседние окрестности для слишком большого скопления, вы откладываете вершины, которые вы сгруппировали в окрестности, и повторяете процесс для остальных данных, пока все вершины не будут учтены. Вы изменяете каждый идентификатор вершины на (вершина, окрестность), и все готово: когда вы следуете за ребрами, вы точно знаете, какую страницу захватить, и большинство из них будут близки, учитывая конструкцию.

Если вам нужны соседние районы, вам нужно будет отслеживать ваши растущие окрестности. Вы повторяете предыдущий процесс (выбираете случайным образом, увеличиваете окрестности), но теперь ранжируете соседей по тому, сколько ребер они удовлетворяют в окрестности и , какая доля их ребер, покидающих окрестность, находится в существующей группе. Вам могут понадобиться весовые коэффициенты, но что-то вроде

score = (# edges within) - (# neighborhoods outside) - (# neighborhoodless edges outside)

вероятно, добьется цели.

Теперь, это не глобально или даже локально оптимально, но это или что-то очень похожее должно дать хорошо локально связанную структуру и позволить вам создать покрывающий набор окрестностей, которые имеют относительно высокая взаимосвязанность.

Опять же, это зависит от того, обрезает ли ваш поиск в ширину ветки или нет. Если это произойдет, недорогая вещь, которую нужно сделать, это максимизировать локальную взаимосвязанность. Если это не то, что нужно сделать, это минимизировать внешнее подключение - и в этом случае я бы предложил просто собрать наборы в ширину до некоторого размера и сохранить их (с дублированием по краям наборов - вы Вы не сильно ограничены местом на жестком диске, не так ли?).

2 голосов
/ 28 января 2010

Возможно, вы захотите посмотреть на HDF5 . Несмотря на то, что H означает Hierarchical, он может хранить графики, проверьте документацию под ключевым словом «Группы», и он предназначен для очень больших наборов данных. Если я правильно понимаю, «файлы» HDF5 могут быть распределены по нескольким файлам. Теперь HDF5 - это только структура данных, плюс набор библиотек для низко- и высокоуровневых манипуляций со структурой данных. Вдобавок ко всему, я понятия не имею о потоковых алгоритмах разбиения графа, но придерживаюсь мнения, что если вы получите правильную структуру данных, алгоритмы станут проще реализовать.

Что вы уже знаете о мега-графе? Естественно ли он разбивается на плотные подграфы, которые сами по себе слабо связаны? Будет ли топологическая сортировка графа лучшей базой для хранения на диске, чем существующая пространственная сортировка?

Если нет четких ответов на такие вопросы, возможно, вам просто нужно прикусить маркер и прочитать график несколько раз, чтобы построить разделы, и в этом случае вам просто нужен самый быстрый ввод-вывод, которым вы можете управлять, и сложное расположение разделов на узлы это хорошо, но не так важно. Если вы можете разбить график на подграфы, у которых есть отдельные ребра к другим подграфам, вы, возможно, сможете сделать задачу более удобной.

Требуется макет, подходящий для BFS, но BFS обычно применяется к деревьям. Есть ли на вашем графике уникальный корень, с которого можно запускать все BFS? Если нет, то компоновка для BFS из одной вершины будет неоптимальной для BFS из другой вершины.

1 голос
/ 05 февраля 2011

Проверьте это сообщение в блоге:

«поиск в ширину первого графа с использованием итеративного алгоритма сокращения карт»

http://www.johnandcailin.com/blog/cailin/breadth-first-graph-search-using-iterative-map-reduce-algorithm

...