Struktura tablic i tablica struktur - różnica wydajności

Mam taką klasę:

//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
    }
};

Tworzę tablicę obiektów typu Unit. I zaktualizuj je.

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

W celu przyspieszenia rzeczy i ewentualnej autowektorizacji pętli przekonwertowałem AoS na strukturę tablic.

//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
    }
  }
};

Gdy pętla nie ulegnie autowektoryzacji, otrzymuję bardzo złą wydajność struktury tablic. Dla 50 jednostek aktualizacja SoA jest nieco szybsza niż AoS. Ale od 100 jednostek SoA jest wolniejsza niż AoS. Przy 300 jednostkach SoA jest prawie dwa razy gorszy. Przy jednostkach 100K, SoA jest 4x wolniejsze niż AoS. Chociaż pamięć podręczna może być problemem dla SoA, nie spodziewałem się, że różnica wydajności będzie tak wysoka. Profilowanie na cachegrind pokazuje podobną liczbę braków dla obu podejść. Rozmiar obiektu Unit wynosi 48 bajtów. Pamięć podręczna L1 to 256K, L2 to 1 MB, a L3 to 8 MB. Czego mi tu brakuje? Czy to naprawdę problem z pamięcią podręczną?

Edytować: Używam gcc 4.5.2. Opcje kompilatora to -o3 -msse4 -wolny-wektoryzacja.

Zrobiłem kolejny eksperyment w SoA. Zamiast dynamicznie alokować tablice, przydzieliłem „v” i „u” w czasie kompilacji. Gdy jest 100K jednostek, daje to wydajność 10 razy większą niż SoA z dynamicznie przydzielanymi tablicami. Co tu się dzieje? Dlaczego istnieje taka różnica wydajności między pamięcią statyczną a dynamicznie przydzielaną?

questionAnswers(4)

yourAnswerToTheQuestion