缓存向量,矩阵和四元数的性能

Eng*_*eer 5 c c++ arrays optimization data-structures

我在过去的很多场合都注意到,C和C++代码对这些结构使用了以下格式:

class Vector3
{
    float components[3];
    //etc.
}

class Matrix4x4
{
    float components[16];
    //etc.
}

class Quaternion
{
    float components[4];
    //etc.
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,这会导致更好的缓存性能,而不是说:

class Quaternion
{
    float x;
    float y;
    float z;
    //etc.
}
Run Code Online (Sandbox Code Playgroud)

...因为我假设类成员和函数在连续的内存空间中,无论如何?我目前使用后一种形式,因为我发现它更方便(但我也可以在数组形式中看到实际意义,因为它允许根据正在执行的操作将轴视为任意).


从受访者那里得到一些建议后,我测试了差异,实际上阵列速度较慢 - 帧率有3%的差异.我实现了operator []来包装Vector3中的数组访问.不确定这是否与它有任何关系,但我怀疑它,因为无论如何应该内联.我能看到的唯一因素是我不能再使用构造函数初始化列表了Vector3(x, y, z).但是当我使用原始版本并将其更改为不再使用构造函数初始化列表时,它的运行速度比以前慢了很多(小于0.05%).毫无头绪,但至少现在我知道原来的方法更快.

Bjö*_*lex 3

这些声明在内存布局方面并不等效。

class Quaternion
{
    float components[4];
    //etc.
}
Run Code Online (Sandbox Code Playgroud)

上面保证了元素在内存中是连续的,而如果它们是像上一个示例一样的单独成员,则允许编译器在它们之间插入填充(例如将成员与某些地址模式对齐)。

这是否会导致更好或更差的性能取决于您的编译器,因此您必须对其进行分析。

  • 虽然规范允许编译器在认为合适的情况下添加填充,但没有编译器在相同类型的对象之间添加与数组元素之间不同的填充,因为这样做是没有意义的。因此,相同类型的多个字段几乎总是像该类型的数组一样进行布局。 (4认同)
  • 您能否给出一个具体的实际示例,其中在后一种情况下会插入填充,而在前一种情况下不会插入填充?或者这纯粹是一个理论论证? (2认同)