Matrix 4x4对象的结构或类

apo*_*pse 5 c# performance

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

xoo*_*ofx 15

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

  • 对GC的不良影响:与可以存储在堆栈上或堆上对象内的值类型不同,对象实例总是在堆上分配,这会给GC带来不必要的压力.例如,如果您需要将World,View和Projection矩阵存储到一个对象中,您将有3个矩阵(原始数据+对象实例的成本~8-12个字节)+ 3个引用:它将创建更多的对象GC必须扫描的堆.使用对象实例有效地执行此操作需要缓存矩阵以便重用它们,而不是我们在矩阵中存储中间计算时使用的模式...
  • 错误数据局部性:值类型的一个重要特征是数据局部性,对象实例无法保证这一点.如果将3种值类型存储到对象实例中,它们将在内存中并置,从而使缓存使用率大大提高.使用object作为矩阵不能保证这一点,并且最有可能导致CPU缓存抖动
  • 糟糕的互操作:3D引擎通常会将其所有计算结果发送到最有可能连接到GPU的底层3D图形层(除非您自己光栅化所有内容,这是一所古老的学校).你经常需要float4x4数组发送到GPU:使用一个对象实例将需要一个循环及复印件到中间float4x4结构格式,以便复制数据,击败有float4x4作为类的全部目的.对于值类型,它只是fixedC#中的单个指令.它也适用于与其他库的互操作(物理引擎将期望float4x4结构而不是对象实例)
  • 坏双:Double几乎不用于3D游戏引擎,因为它们占用更多空间,因此在CPU缓存中占用更多空间.此外,处理GPU意味着您主要使用浮动.它对CPU SSE指令也不友好,这些指令针对在单个指令中执行4个浮点运算进行了优化,但在单个指令中只有2个双重运算.因此,它是不使用双存储矩阵,除非你有一个好主意,非常好的原因(例如,你想提高时,"矩阵的计算收紧视角渲染的精密 ")
  • 不可变性:避免使用矩阵的不变性前提.除非你要在多个线程中围绕所有计算大量浮动,否则你要确保不会搞砸事情.这种结构的不可变性是完全矫枉过正的.想象一下将转换应用于矩阵的非常简单的场景,使用可变结构,您只需要更新一行.使用不可变结构,您需要在复制初始值时创建新的整个矩阵.

另外,如果你关心表现:

  • 如果您需要在类中存储valuetype矩阵,则更喜欢将它们存储在公共字段而不是公共属性中,因为它将在访问矩阵时避免不必要的副本.您还可以直接固定矩阵以将其移动到非托管内存
  • 相关的,更喜欢ref在所有矩阵计算中通过而不是通过复制传递矩阵.