Estrutura de arrays e matriz de estruturas - diferença de desempenho
Eu tenho uma aula assim:
//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
}
};
Eu crio uma matriz de objetos do tipo Unit. E ligue para atualizar sobre eles.
int NUM_UNITS = 10000;
void ProcessUpdate()
{
Unit *units = new Unit[NUM_UNITS];
for(int i = 0; i < NUM_UNITS; i++)
{
units[i].update();
}
}
A fim de acelerar as coisas e, possivelmente, autovectorize o loop, converti o AoS em estrutura de matrizes.
//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
}
}
};
Quando o loop não consegue se autovectorizar, estou obtendo um desempenho muito ruim para a estrutura de matrizes. Para 50 unidades, a atualização do SoA é ligeiramente mais rápida que o AoS.But, a partir de 100 unidades em diante, o SoA é mais lento que o AoS. Em 300 unidades, o SoA é quase duas vezes pior. Em 100K unidades, o SoA é 4x mais lento que o AoS. Embora o cache possa ser um problema para o SoA, não esperava que a diferença de desempenho fosse tão alta. A criação de perfil no cachegrind mostra um número semelhante de erros para ambas as abordagens. Tamanho de um objeto Unit é de 48 bytes. O cache L1 é 256K, o L2 é 1MB e o L3 é 8MB. O que estou perdendo aqui? Isso é realmente um problema de cache?
Editar: Eu estou usando o gcc 4.5.2. As opções do compilador são -o3 -msse4 -ftree-vectorize.
Eu fiz outro experimento no SoA. Em vez de alocar dinamicamente as matrizes, aloquei "v" e "u" em tempo de compilação. Quando há 100 mil unidades, isso gera um desempenho 10 vezes mais rápido do que o SoA com matrizes alocadas dinamicamente. O que está acontecendo aqui? Por que existe essa diferença de desempenho entre a memória alocada estática e dinamicamente?