向量,矩阵和四元数的缓存性能
Cache performance of vectors, matrices and quaternions
我注意到在过去的许多场合,C和c++代码对这些结构使用以下格式:
class Vector3
{
float components[3];
//etc.
}
class Matrix4x4
{
float components[16];
//etc.
}
class Quaternion
{
float components[4];
//etc.
}
我的问题是,这会导致更好的缓存性能比说,这:
class Quaternion
{
float x;
float y;
float z;
//etc.
}
…既然我假设类成员和函数是在连续的内存空间,无论如何?我目前使用后一种形式,因为我发现它更方便(然而,我也可以在数组形式中看到实际意义,因为它允许人们将轴视为任意依赖于正在执行的操作)。
在听取了受访者的一些建议后,我测试了差异,它实际上比阵列慢——我在帧率上得到了大约3%的差异。我实现了操作符[]将数组访问封装在Vector3中。不确定这是否与它有任何关系,但我怀疑它,因为它应该是内联的。我能看到的唯一因素是我不能再在Vector3(x, y, z)
上使用构造函数初始化列表。然而,当我采用原始版本并将其更改为不再使用构造函数初始化器列表时,它的运行速度比以前慢得多(不到0.05%)。不知道,但至少现在我知道原来的方法更快。
这些声明对于内存布局来说是不等价的。
class Quaternion
{
float components[4];
//etc.
}
以上保证了元素在内存中是连续的,然而,如果它们是单独的成员,就像上一个例子中一样,编译器允许在它们之间插入填充(例如,以特定的地址模式对齐成员)。
这是否会导致更好或更差的性能主要取决于您的编译器,所以您必须对其进行配置。
我认为这样的优化带来的性能差异是最小的。我想说,对于大多数代码来说,这样的事情属于过早优化。然而,如果你计划在你的结构上做矢量处理,比如通过使用CUDA,结构组合会产生重要的区别。如果感兴趣,请参阅第23页:http://www.eecis.udel.edu/~mpellegr/eleg662-09s/li.pdf
我不确定在这种情况下使用数组时编译器是否能够更好地优化代码(例如,在联合中考虑),但是当使用像OpenGL这样的api时,它可以在调用像
这样的函数时进行优化void glVertex3fv(const GLfloat* v);
而不是调用
void glVertex3f(GLfloat x, GLfloat y, GLfloat z);
,因为在后一种情况下,每个形参都是按值传递的,而在第一个例子中,只传递指向整个数组的指针,函数可以决定复制什么以及何时复制,这样可以减少不必要的复制操作。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- OpenMP阵列性能较差
- 递归列出所有目录中的C++与Python与Ruby的性能
- 大小相等但成员数量不同的结构之间的性能差异
- cmake更新缓存的变量
- 为什么constexpr的性能比正常表达式差
- 试图对缓存进行跨步测试,但程序并没有结束
- 在类中使用随机生成器时出现性能问题
- 迭代时的性能(缓存未命中)
- 高速缓存行检索和在大型数据结构上的性能
- "non-native"指针会损害缓存性能吗?
- 如何使用缓存技术提高性能
- OOP是否鼓励良好的缓存,从而提高性能
- 指针在内存缓存方面的性能
- 向量,矩阵和四元数的缓存性能
- 缓存位置性能
- C++缓存性能奇怪的行为
- C++池分配器与静态分配,缓存性能
- 2bit位域数组对性能和缓存效率的影响
- 用于缓存和内存总线性能的工具或代码