减少可变共享状态
因此,我正在学习光线追踪教程,试图扩展我的 F# 腿。由于本教程是用 C++ 编写的,因此弄清楚如何以函数式方式应用这些概念是一个相当有趣的挑战。我想以尽可能实用的方式编写所有内容,因为我打算最终并行运行光线追踪器。但这让我遇到了以下情况,我确信其核心出现在光线追踪以外的主题中。
我们有一个 Engine
对象(除其他外)存储一个 Scene
对象(Primitive
对象的集合)。目前,Scene
和其中的 Primitive
是完全不可变的。
为了尝试缩短渲染时间,我们正在实现常规的三维网格。为了有效地遍历网格,教程参考了这篇论文 用于遍历算法,以及减少跨网格边界的图元的相交测试的数量。后一部分的工作原理如下:
- 每个
Ray
都分配有一个唯一的rayID
- 每个
Primitive
都有一个lastRayID
字段。 - 当
Ray
检查与Primitive
的交集时,- 如果
Ray
的rayID
等于Primitive
的lastRayID
,则跳过相交测试. - 否则,执行测试,并将
Ray
的rayID
存储在Primitive< 的
lastRayID
字段中/代码>。
- 如果
这是缓存相交测试的一种巧妙方法,但它是为顺序光线追踪器设置的,甚至对于两条并发光线也根本不起作用。因此,尽管我可以使用可变字段,从而能够实现此算法,但它无法满足我的本质上可并行的光线追踪器的最终目标。
我确实有一个想法。为每个图元存储可变状态的问题在于,就渲染算法而言,场景是一个全局实体 - 每条光线都可能撞击任何图元。另一方面,每条射线都是完全独立的。因此,在每条光线中,我认为我可以构建一组已经过测试的基元(该组相当于上述的 lastRayID
字段)。这样做的问题是,每条光线的生命周期极短,并且在任何给定时间都可能存在许多光线,因此在每条光线中设置这样的数据结构可能会耗费大量的((或取消)分配时间和内存)消耗成本可能会迅速增加)
有人对处理此类情况有建议吗?即使这是将共享可变状态转换为本地可变状态或类似的东西的一般想法,我相信这会对我有很大帮助。如有必要,我很乐意澄清任何事情。
So I'm going through a ray tracing tutorial in an attempt to stretch my F# legs. Since the tutorial is written in C++, it a rather fun challenge to figure out how to apply the concepts in a functional manner. I'd like to write everything in as functional a manner as possible, because I intend to eventually run the ray tracer in parallel. But that got me to the following situation, the core of which I'm sure shows up in topics other than ray tracing.
We have an Engine
object which (among other things) stores a Scene
object (a collection of Primitive
objects). Currently, the Scene
and the Primitive
s within it are completely immutable.
To try improve the rendering time, we're implementing a regular three-dimensional grid. In order to traverse the grid in an effective manner, the tutorial references this paper for the both the traversal algorithm, and for reducing the number of intersection tests for primitives which lie across grid boundaries. Here's how the latter part works:
- Each
Ray
is assigned a uniquerayID
- Each
Primitive
has alastRayID
field. - When a
Ray
checks for intersection with aPrimitive
,- If the
rayID
of theRay
equals thelastRayID
of thePrimitive
, then the intersection test is skipped. - Otherwise, the test is performed, and the
rayID
of theRay
is stored in thelastRayID
field of thePrimitive
.
- If the
This is a neat way of caching the intersection tests, but it's set up for a sequential ray tracer, and wouldn't work at all for even two concurrent rays. So although I could use mutable
fields, and therefore be able to implement this algorithm, it wouldn't satify my end goals of an inherently parallelizable ray tracer.
I do have one idea. The problem with storing mutable state with each primitive is that, with respect to the rendering algorithm, the scene is a global entity - each ray could potentially strike any primitive. On the other hand, each ray is completely self contained. So in each ray, I figured I could build up a set of primitives which have already been tested against (this set would be the equivalent to the lastRayID
field described above). The problem with this is that each ray has an extremely short life time, and there could potentially be many rays in existence at any given time, so setting up such a data structure in each ray could be costly ((de)allocation time and memory consumption costs could add up quickly)
Does anyone have advice on dealing with these kinds of situations? Even if it's a general idea about transforming shared mutable state into local mutable state or something like that, I'm sure that would help me out a lot. I'd be happy to clarify anything if necessary.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论