我有一个类是这样的:结构 - 性能差
//Array of Structures
class Unit
{
public:
float v;
float u;
//And similarly many other variables of float type, upto 10-12 of them.
void update()
{
v+=u;
v=v*i*t;
//And many other equations
}
};
创建单元类型的对象的数组。并致电更新。
int NUM_UNITS = 10000;
void ProcessUpdate()
{
Unit *units = new Unit[NUM_UNITS];
for(int i = 0; i < NUM_UNITS; i++)
{
units[i].update();
}
}
为了加快速度,可能会自动化循环,我将AoS转换为数组结构。
//Structure of Arrays:
class Unit
{
public:
Unit(int NUM_UNITS)
{
v = new float[NUM_UNITS];
}
float *v;
float *u;
//Mnay other variables
void update()
{
for(int i = 0; i < NUM_UNITS; i++)
{
v[i]+=u[i];
//Many other equations
}
}
};
当循环失败autovectorize,我得到一个非常糟糕的性能的数组结构。对于50个单位,SoA的更新比AoS稍快。但从100个单位开始,SoA比AoS慢。在300台机组中,SoA差不多是它的两倍。在100K单位,SoA比AoS慢4倍。虽然缓存可能是SoA的一个问题,但我并没有预料到性能差异会如此之高。对cachegrind进行性能分析,显示两种方法的缺失数量相似。 Unit对象的大小是48个字节。 L1缓存为256K,L2为1MB,L3为8MB。我在这里错过了什么?这真的是缓存问题吗?
编辑: 我使用的是gcc 4.5.2。编译器选项是-o3 -msse4 -ftree-vectorize。
我在SoA做了另一个实验。我没有动态分配数组,而是在编译时分配了“v”和“u”。当有100K个单元时,这个性能比具有动态分配阵列的SoA快10倍。这里发生了什么事?为什么静态和动态分配内存之间存在性能差异?
你用什么编译器选项来构建它? – 2012-07-23 16:57:23
不知道这是否会有所作为,但[std :: valarray](http://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a00738.html)可能会(或可能不会) ) 帮帮我。它被设计用于在整个数组上执行数学运算(比较干净的语法),但是我猜测实现者有特殊的重载来尝试优化这些操作并在可能时进行智能分配等。它可能根本没有帮助,但可能值得一看。 – pstrjds 2012-07-23 17:16:54
在运行基准测试之前将数据集清零会发生什么?未初始化的浮点很有可能被[非规范化](http://stackoverflow.com/a/9314926/922184)。你不想那样搞砸你的基准。 – Mysticial 2012-07-25 03:27:28