나는 수업이 같이 있습니다구조 - 성능 차이
//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
}
};
I 단위 유형의 객체의 배열을 만들 수 있습니다. 그리고 그들에 대한 업데이트를 호출하십시오.
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
}
}
};
루프가 자동 수신에 실패하면 배열 구조가 매우 저하됩니다. 50 대는 SoA의 업데이트가 AoS보다 약간 빠릅니다.하지만 100 대 이상부터 SoA는 AoS보다 느립니다. 300 대에서 SoA는 거의 두 배 더 나 빠졌습니다. 100K 단위에서 SoA는 AoS보다 4 배 느립니다. 캐시가 SoA에 대한 문제 일 수는 있지만 성능 차이가 높을 것으로 기대하지 않았습니다. 캐시 그 린드 (cachegrind)에 대한 프로파일 링은 두 접근법 모두에서 유사한 누락 횟수를 보여줍니다. 단위 개체의 크기는 48 바이트입니다. L1 캐시는 256K, L2는 1MB, L3은 8MB입니다. 내가 여기서 무엇을 놓치고 있니? 이 문제는 실제로 캐시 문제입니까?
편집 : gcc 4.5.2를 사용 중입니다. 컴파일러 옵션은 -o3 -msse4 -ftree-vectorize입니다.
SoA에서 또 다른 실험을했습니다. 동적으로 배열을 할당하는 대신 컴파일 타임에 "v"와 "u"를 할당했습니다. 100K 단위가있을 때 동적으로 할당 된 배열을 사용하는 SoA보다 10 배 빠른 성능을 제공합니다. 여기서 뭐하는거야? 정적 메모리와 동적으로 할당 된 메모리간에 성능 차이가있는 이유는 무엇입니까?
빌드 할 때 어떤 컴파일러 옵션을 사용합니까? –
이것이 차이를 만들지는 모르겠지만 [std :: valarray] (http://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a00738.html)는) 도움. 그것은 전체 배열 (그런 식으로 깨끗한 구문)에 수학 연산을 수행하기 위해 설계되었습니다하지만 나는 implementers 그 작업을 최적화하고 가능하면 지능형 할당 등을하려고 특별한 과부하가 있다고 생각합니다. 그것은 전혀 도움이되지 않을지도 모르지만,보기 가치가 있을지도 모르다. – pstrjds
벤치 마크를 실행하기 전에 데이터 집합을 0으로 만들면 어떻게됩니까? 초기화되지 않은 부동 소수점은 [비정규 화 된] 가능성이 높습니다 (http://stackoverflow.com/a/9314926/922184). 벤치 마크를 망치고 싶지는 않습니다. – Mysticial