减少可变共享状态

发布于 2024-12-20 01:42:11 字数 1367 浏览 3 评论 0原文

因此,我正在学习光线追踪教程,试图扩展我的 F# 腿。由于本教程是用 C++ 编写的,因此弄清楚如何以函数式方式应用这些概念是一个相当有趣的挑战。我想以尽可能实用的方式编写所有内容,因为我打算最终并行运行光线追踪器。但这让我遇到了以下情况,我确信其核心出现在光线追踪以外的主题中。

我们有一个 Engine 对象(除其他外)存储一个 Scene 对象(Primitive 对象的集合)。目前,Scene 和其中的 Primitive 是完全不可变的。

为了尝试缩短渲染时间,我们正在实现常规的三维网格。为了有效地遍历网格,教程参考了这篇论文 用于遍历算法,以及减少跨网格边界的图元的相交测试的数量。后一部分的工作原理如下:

  • 每个 Ray 都分配有一个唯一的 rayID
  • 每个 Primitive 都有一个 lastRayID 字段。
  • Ray检查与Primitive的交集时,
    1. 如果RayrayID等于PrimitivelastRayID,则跳过相交测试.
    2. 否则,执行测试,并将 RayrayID 存储在 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 Primitives 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 unique rayID
  • Each Primitive has a lastRayID field.
  • When a Ray checks for intersection with a Primitive,
    1. If the rayID of the Ray equals the lastRayID of the Primitive, then the intersection test is skipped.
    2. Otherwise, the test is performed, and the rayID of the Ray is stored in the lastRayID field of the Primitive.

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文