数组结构和结构数组 - 性能差异

exc*_*ray 13 c c++ performance gcc caching

我有一个这样的课:

//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
    }
};
Run Code Online (Sandbox Code Playgroud)

我创建了一个Unit类型的对象数组.并调用它们的更新.

int NUM_UNITS = 10000;
void ProcessUpdate()
{
  Unit *units = new Unit[NUM_UNITS];
  for(int i = 0; i < NUM_UNITS; i++)
  {
    units[i].update();
  }
}
Run Code Online (Sandbox Code Playgroud)

为了加快速度,并可能对循环进行自动调整,我将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
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

当循环无法自动向量化时,我的数组结构的性能非常糟糕.对于50个单位,SoA的更新速度略快于AoS.But然后从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倍.这里发生了什么事?为什么静态和动态分配的内存之间存在这样的性能差异?

Ser*_* K. 10

在这种情况下,数组的结构不是缓存友好的.

您可以使用这两个uv在一起,但在他们2个不同阵列的情况下,他们不会同时加载到一个高速缓存行和高速缓存未命中将耗资巨大的性能损失.

_mm_prefetch可用于AoS更快地进行表示.

  • 然而,缓存未命中并没有被部分浪费 - 你得到的东西是你需要的东西(更多的是你的和更多的'v`),那为什么会降低性能? (2认同)