Я реализовал итерационный алгоритм, где каждая итерация включает в себя обход дерева предзаказов (иногда называемый вниз накоплением), за которым следует обход дерева после заказа (вверх накопление). Каждое посещение каждого узла включает в себя вычисление и хранение информации, которая будет использоваться для следующего посещения (либо в последующем последующем обходе, либо в последующей итерации).Стратегия параллельной реализации алгоритма пересечения деревьев?
Во время предварительного обхода каждый узел может обрабатываться независимо, если все узлы между ним и корнем уже обработаны. После обработки каждому узлу необходимо передать кортеж (в частности, два поплавка) каждому из своих дочерних элементов. При обходе после заказа каждый узел может обрабатываться независимо до тех пор, пока все его поддеревья (если они есть) уже обработаны. После обработки каждому узлу необходимо передать один поплавок своему родительскому элементу.
Структура деревьев является статической и неизменной во время алгоритма. Однако в ходе нисходящего обхода, если два поплавка передаются, оба становятся равными нулю, все поддерево под этим узлом не нужно обрабатывать, и начальный обход для этого узла может начаться. (Поддерево должно быть сохранено, потому что прошедшие поплавки на последующих итерациях могут стать ненулевыми на этом узле, и обход продолжится).
Интенсивность вычислений на каждом узле одинакова по дереву. Вычисление на каждом узле тривиально: всего несколько сумм и умножение/деление на список чисел с длиной, равной числу детей в узле.
Обработанные деревья неуравновешены: типичный узел будет иметь 2 листа плюс 0-6 дополнительных дочерних узлов. Таким образом, простое разбиение дерева на множество относительно сбалансированных поддеревьев неочевидно (для меня). Кроме того, деревья предназначены для использования всей доступной оперативной памяти: большее дерево, которое я могу обработать, тем лучше.
Моя серийная реализация достигает порядка 1000 итераций в секунду только на моих маленьких тестовых деревьях; с «реальными» деревьями, я ожидаю, что он может замедляться на порядок (или больше?). Учитывая, что для достижения приемлемого результата для алгоритма требуется не менее 100 миллионов итераций (возможно, до миллиарда), я хотел бы распараллелить алгоритм, чтобы воспользоваться преимуществами нескольких ядер. У меня нет опыта параллельного программирования.
Каков рекомендуемый шаблон для распараллеливания с учетом характера моего алгоритма?
Первый шаг - анализ вашего алгоритма для определения того, какие части, если таковые имеются, независимы друг от друга. Это, вероятно, потребует, чтобы вы рассматривали свой алгоритм на более низком уровне, чем вы здесь. –
Точно, какие деревья вы обрабатываете, и какие операции вам нужно поддерживать? Прежде чем вы рассмотрите параллельный обход дерева, спросите себя, можете ли вы переписать свои деревья с использованием лучшей структуры данных или улучшить операцию O (n) в O (log n). – Juliet
Есть ли общие данные между узлами дерева или они логически отделимы? Я могу предложить некоторые достойные предложения, но более подробно это облегчило бы. – Novelocrat