我有一個類是這樣的:結構 - 性能差
//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