c# - Matrix 4x4 对象的结构或类

标签 c# performance

我正在尝试实现简单的软件 3D 引擎。所以我需要一个 4x4 矩阵来表示转换。我的矩阵的每个单元格类型都采用 System.Double 格式,这意味着整个矩阵将使用 8 字节 * 16 个单元格 = 128 字节。目前我已经将其实现为一个类。此矩阵也是不可变类型。
所以现在,当我尝试用这个矩阵乘以向量时,我正在做这样的事情:matrix.m11 * vector.X(等...)。正如我所想,要访问字段 m11,程序首先需要获取“矩阵”引用值,然后检查它是否为空,然后找到 m11 值,是吗?如果我将类更改为结构,我的乘法会更快吗?我知道 128 字节的结构很大,但是如果我编写仅使用 ref/out keyowrds 的方法呢?会好选择吗?
正如我在 SharpDX 库中看到的那样,矩阵是一个结构。我应该将类更改为结构然后以提高性能吗?

最佳答案

出于以下原因,我不建议使用类来存储 3D 引擎的 double4x4 矩阵:

  • 对 GC 的不良影响:与可以存储在堆栈或堆上的对象内部的值类型不同,对象实例总是在堆上分配,这会给 GC 带来不必要的压力.例如,如果您需要将世界、 View 和投影矩阵存储到一个对象中,您将有 3 个矩阵(原始数据 + 对象实例的成本 ~ 8-12 字节)+ 3 个引用:它将在GC 必须扫描的堆。使用对象实例有效地执行此操作需要缓存您的矩阵以便重用它们,而不是我们在仅将中间计算存储在矩阵上时使用的那种模式......
  • 糟糕的数据局部性:值类型的一个重要特征是数据局部性,对象实例不能保证这一点。如果将 3 种值类型存储到一个对象实例中,它们将在内存中并置,从而导致更好的缓存使用。使用对象作为矩阵不能保证这一点,很可能会导致 CPU cache thrashing
  • 互操作性差:3D 引擎通常会将其所有计算发送到最有可能连接到 GPU 的底层 3D 图形层(除非您自己对所有内容进行栅格化,这是一种老派做法)。您经常需要向 GPU 发送一个 float4x4 数组:使用对象实例需要一个循环和一个到中间 float4x4 结构格式的副本,以便复制数据,这违背了将 float4x4 作为类的全部目的。对于值类型,它只是 C# 中的单个 fixed 指令。它还适用于与其他库的互操作(物理引擎需要 float4x4 结构,而不是对象实例)
  • Bad double:Double 在 3D 游戏引擎中几乎不使用,因为它们占用更多空间,因此占用更多 CPU 缓存空间。此外,处理 GPU 意味着您主要使用 float 。它也不适合 CPU SSE 指令,这些指令经过优化可以在一条指令中执行 4 个浮点运算,但在一条指令中只能执行 2 个 double 运算。所以使用 double 来存储矩阵不是一个好主意,除非你有一个非常好的理由(例如,你想在“Tightening the Precision of Perspective Rendering”时改进矩阵的计算)<
  • Bad immutability :避免使用矩阵不变性的前提。除非你要在多线程中大量地处理你的所有计算,并且你想确保你不会把事情搞砸。这种结构的不可变性完全是矫枉过正。想象一下将翻译应用于矩阵的非常简单的场景,带有 mutable struct ,你只需要更新一行。对于不可变结构,您需要在复制初始值的同时创建一个新的完整矩阵。

附带说明一下,如果您关心性能:

  • 如果您需要在类中存储值类型矩阵,最好将它们存储在公共(public)字段而不是公共(public)属性中,因为这样可以避免在访问矩阵时进行不必要的复制。您还可以直接固定矩阵以将其移动到非托管内存
  • 相关,在所有矩阵计算中更喜欢通过 ref 而不是通过复制来传递矩阵。

关于c# - Matrix 4x4 对象的结构或类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24231389/

相关文章:

javascript - 无卡顿体验和 websocket

c - 哪种USB读取模式效率更高 : Multiple reads or one big read?

c# - 在回发时保持滚动位置不起作用

c# - TaskCompletionSource.SetResult 的线程安全

C# 接口(interface)调试信息未链接到源

mysql - 如何使用 group by、where 和 order by 子句在大表(>38.700.000 行)上定义索引

c# - C# 中真随机数生成器的最快实现

performance - 为什么 atan2(y,x) 的计算速度比 arcsin 或 arccos 快?

c# - c#中的类库是否有等效的Application_Start

c# - 在 RowDoubleClicked Blazorise DataGrid 上显示 DetailRow