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