Как в древовидной структуре Unity/C# суммировать вычисленные значения от корня до листьев с помощью ComputeShaders? ⇐ C#
Как в древовидной структуре Unity/C# суммировать вычисленные значения от корня до листьев с помощью ComputeShaders?
Это не было бы слишком сложно, если бы не смешивание нескольких миров: мира алгоритмики, мира C# и мира вычислительных шейдеров (в Unity).
Вот как моя структура выглядит на C# (упрощенно для объяснения):
класс Функция { общедоступный тип int; // 0 или 1 общественный int параметр1; общественный int param2; } класс Узел { идентификатор общедоступной строки; общедоступный список Функции; общедоступный список Children; } После загрузки вы можете представить его вот так, если он был отрендерен в стиле json:
{ "идентификатор": "узел0", "функции": [ { "тип": 0, "параметр1": 5, "параметр2": 6}, { "тип": 1, "парам1": 7, "парам2": 8} ], "дети": [ { "идентификатор": "узел00", "функции": [ { "тип": 0, "парам1": 9, "парам2": 10}, { «тип»: 1, «парам1»: 11, «парам2»: 12} ], "дети": [ { "идентификатор": "узел000", "функции": [ { "тип": 0, "парам1": 13, "парам2": 14}, { "тип": 1, "парам1": 15, "парам2": 16}, ], "дети": [] //это лист } ] }, { "идентификатор": "узел01", "функции": [{ "тип": 0, "параметр1": 15, "параметр2": 16}], "дети": [] // тоже лист } ] } Я хочу использовать вычислительные шейдеры для вычисления «значения» каждого узла (а не только листьев!) значение каждого узла рассчитывается следующим образом:
[*]Вычислить каждую из его функций [*]Суммируйте все результаты тех же функций. [*]Суммируйте все функции всех родительских элементов вплоть до корня.
Например, node000 будет рассчитываться следующим образом:
int result0 = ComputeFunction(тип: 0, параметр1: 13, параметр2: 14); int result1 = ComputeFunction (тип: 1, параметр 1: 15, параметр 2: 16); int node000Sum = result0 + result1 // терминов может быть столько, сколько функций в узле. // (не подробно): повторение с родительским узлом node00 // (не подробно): повторите с прародителем node0, который также является корневым. int FinalResult = node000Sum + node00Sum + node0Sum Нам не просто нужна окончательная сумма листьев. Мы также будем использовать node00Sum и node0Sum везде, где это необходимо (другими словами: результат вычислений каждого узла где-то используется).
===================
Такова была установка. Теперь моя проблема: я не могу представить, как организовать эти данные, чтобы они эффективно обрабатывались вычислительным шейдером.
Я думал, что самый простой первый шаг — это сохранить все функции всех узлов в одном большом плоском массиве (псевдо- json): всеФункции: [ { «тип»: 0, «параметр1»: 5, «параметр2»: 6}, { "тип": 1, "парам1": 7, "параметр2": 8}, { «тип»: 0, «парам1»: 9, «параметр2»: 10}, { "тип": 1, "парам1": 11, "парам2": 12}, { «тип»: 0, «парам1»: 13, «парам2»: 14}, { "тип": 1, "парам1": 15, "парам2": 16}, { «тип»: 0, «парам1»: 15, «парам2»: 16} ]
...Затем шейдер вычислит каждую функцию (и только ее).
... затем (возможно) сделайте второй проход шейдера для вычисления сумм... (в противном случае сделайте это на C#, если это слишком сложно). ...затем сопоставьте эти суммы с исходным узлом, которому они принадлежат.
Но что бы я ни делал, структура данных быстро становится головной болью.
Создать массив всех функций и вычислить их легко, но подсчитать суммы и сопоставить их с узлами сложно. Для эффективности мне приходится работать с массивами (шейдеры не обрабатывают связанные списки), но мне также нужно как-то «запомнить» древовидную структуру. В результате я быстро запутываюсь в каких-то бедняцких связанных списках (и дереве в целом), пытаясь жонглировать индексами элементов массива.
И даже если мне это удастся, то будет сложно сопоставить суммы с исходными узлами.
Как бы вы этого достигли? (т.е. что необходимо изменить в общем подходе)? Есть ли подобная проблема в литературе? (Могу поспорить, что есть, но мне не нужна степень доктора философии, чтобы понять это.)
Это не было бы слишком сложно, если бы не смешивание нескольких миров: мира алгоритмики, мира C# и мира вычислительных шейдеров (в Unity).
Вот как моя структура выглядит на C# (упрощенно для объяснения):
класс Функция { общедоступный тип int; // 0 или 1 общественный int параметр1; общественный int param2; } класс Узел { идентификатор общедоступной строки; общедоступный список Функции; общедоступный список Children; } После загрузки вы можете представить его вот так, если он был отрендерен в стиле json:
{ "идентификатор": "узел0", "функции": [ { "тип": 0, "параметр1": 5, "параметр2": 6}, { "тип": 1, "парам1": 7, "парам2": 8} ], "дети": [ { "идентификатор": "узел00", "функции": [ { "тип": 0, "парам1": 9, "парам2": 10}, { «тип»: 1, «парам1»: 11, «парам2»: 12} ], "дети": [ { "идентификатор": "узел000", "функции": [ { "тип": 0, "парам1": 13, "парам2": 14}, { "тип": 1, "парам1": 15, "парам2": 16}, ], "дети": [] //это лист } ] }, { "идентификатор": "узел01", "функции": [{ "тип": 0, "параметр1": 15, "параметр2": 16}], "дети": [] // тоже лист } ] } Я хочу использовать вычислительные шейдеры для вычисления «значения» каждого узла (а не только листьев!) значение каждого узла рассчитывается следующим образом:
[*]Вычислить каждую из его функций [*]Суммируйте все результаты тех же функций. [*]Суммируйте все функции всех родительских элементов вплоть до корня.
Например, node000 будет рассчитываться следующим образом:
int result0 = ComputeFunction(тип: 0, параметр1: 13, параметр2: 14); int result1 = ComputeFunction (тип: 1, параметр 1: 15, параметр 2: 16); int node000Sum = result0 + result1 // терминов может быть столько, сколько функций в узле. // (не подробно): повторение с родительским узлом node00 // (не подробно): повторите с прародителем node0, который также является корневым. int FinalResult = node000Sum + node00Sum + node0Sum Нам не просто нужна окончательная сумма листьев. Мы также будем использовать node00Sum и node0Sum везде, где это необходимо (другими словами: результат вычислений каждого узла где-то используется).
===================
Такова была установка. Теперь моя проблема: я не могу представить, как организовать эти данные, чтобы они эффективно обрабатывались вычислительным шейдером.
Я думал, что самый простой первый шаг — это сохранить все функции всех узлов в одном большом плоском массиве (псевдо- json): всеФункции: [ { «тип»: 0, «параметр1»: 5, «параметр2»: 6}, { "тип": 1, "парам1": 7, "параметр2": 8}, { «тип»: 0, «парам1»: 9, «параметр2»: 10}, { "тип": 1, "парам1": 11, "парам2": 12}, { «тип»: 0, «парам1»: 13, «парам2»: 14}, { "тип": 1, "парам1": 15, "парам2": 16}, { «тип»: 0, «парам1»: 15, «парам2»: 16} ]
...Затем шейдер вычислит каждую функцию (и только ее).
... затем (возможно) сделайте второй проход шейдера для вычисления сумм... (в противном случае сделайте это на C#, если это слишком сложно). ...затем сопоставьте эти суммы с исходным узлом, которому они принадлежат.
Но что бы я ни делал, структура данных быстро становится головной болью.
Создать массив всех функций и вычислить их легко, но подсчитать суммы и сопоставить их с узлами сложно. Для эффективности мне приходится работать с массивами (шейдеры не обрабатывают связанные списки), но мне также нужно как-то «запомнить» древовидную структуру. В результате я быстро запутываюсь в каких-то бедняцких связанных списках (и дереве в целом), пытаясь жонглировать индексами элементов массива.
И даже если мне это удастся, то будет сложно сопоставить суммы с исходными узлами.
Как бы вы этого достигли? (т.е. что необходимо изменить в общем подходе)? Есть ли подобная проблема в литературе? (Могу поспорить, что есть, но мне не нужна степень доктора философии, чтобы понять это.)
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение