У меня есть следующая проблема: мне нужно вычислить включенные проверки (например, prefix sums) значений на основе древовидной структуры на графическом процессоре. Эти проверки выполняются либо из корневого узла (сверху вниз), либо из листовых узлов (снизу вверх). Случай простой цепи - easily handled, но древовидная структура делает распараллеливание довольно сложным для эффективной реализации.Включенное сканирование на основе графического процессора на неуравновешенном дереве
Например, после того, как сверху вниз включительно сканирования, (12)
проведет (0)[op](6)[op](7)[op](8)[op](11)[op](12)
, и снизу вверх включительно сканирования, (8)
проведет (8)[op](9)[op](10)[op](11)[op](12)
, где [op]
является данный бинарный оператор (матрица сложения, умножение и т. д.).
Кроме того, нужно учитывать следующие моменты:
- Для типичного сценария, длина различных ветвей не должна быть слишком длинной (~ 10), с чем-то вроде 5 до 10 ветвей, так что это то, что будет выполняться внутри блока, и работа будет разделена между потоками. Различные блоки будут просто обрабатывать разные значения узлов. Это, очевидно, не является оптимальным в отношении занятости, но это ограничение проблемы, которая будет решена через некоторое время. На данный момент я буду полагаться на Instruction-level parallelism.
- Структура диаграммы не может быть изменена (она описывает реальную систему), поэтому она не может быть сбалансирована (или только путем изменения корня дерева, например, с использованием
(6)
в качестве нового корня). Тем не менее, типичное дерево не должно быть слишком неуравновешенным. - В настоящее время я использую CUDA для GPGPU, поэтому я открыт для любой библиотеки шаблонов с поддержкой CUDA, которая может решить эту проблему.
- Узел данных уже находится в глобальной памяти, и результат будет использоваться другими ядрами CUDA, поэтому цель заключается в достижении этого, не делая этого огромным узким местом.
- Не существует «цикла», то есть ветви не могут сливаться с деревом.
- Структура дерева фиксирована и задана в фазе инициализации.
- Одна бинарная операция может быть довольно высокой (например, умножение полиномиальных матриц, т.е. каждый элемент является многочленом заданного порядка).
В этом случае, какая была бы «лучшая» структура данных (для древовидной структуры) и лучшие алгоритмы (для включенных сканирований/префиксов) для решения этой проблемы?
Высокий вопрос. Нам нужно больше этого типа вопроса и меньше основных вопросов по исправлению ошибок, которые мы получаем все время. –
Размер проблемы настолько мал (10 ветвей x 10 заметок/ветвь). Я предполагаю, что даже если вы используете только 1 поток для вычисления всех префикс-сумм для всех узлов, затраты времени можно игнорировать по сравнению с другими частями кода, который выполняется на графическом процессоре. – kangshiyin
@ Эрик: дело в том, что каждый узел фактически обрабатывает довольно много вычислений (например, полиномиальные матрицы, которые нужно умножать), поэтому последовательный алгоритм становится узким местом. Я пробовал это с помощью простых цепей, и более разумный логарифмический подход обеспечивал нестандартное ускорение. – BenC