Уменьшение изменяемого общего состояния - PullRequest
1 голос
/ 07 декабря 2011

Итак, я прохожу учебник по трассировке лучей в попытке растянуть мои ноги F #. Поскольку учебное пособие написано на C ++, довольно сложно понять, как применять концепции функциональным образом. Я хотел бы написать все настолько функционально, насколько это возможно, потому что я намерен в конечном итоге запустить трассировщик лучей параллельно. Но это привело меня к следующей ситуации, суть которой, я уверен, проявляется в других темах, кроме трассировки лучей.

У нас есть объект Engine, который (помимо прочего) хранит объект Scene (набор объектов Primitive). В настоящее время Scene и Primitive в нем полностью неизменны.

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

  • Каждому Ray присваивается уникальный rayID
  • Каждый Primitive имеет поле lastRayID.
  • Когда Ray проверяет пересечение с Primitive,
    1. Если rayID из Ray равно lastRayID из Primitive, тогда тест пересечения пропускается.
    2. В противном случае выполняется проверка, и rayID из Ray сохраняется в поле lastRayID в Primitive.

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

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

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

...