このクラスを受けて、
アプローチ 1:
typedef float v4sf __attribute__ (vector_size(16))
class Unit
{
public:
Unit(int num)
{
u = new float[num];
v = new float[num];
}
void update()
{
for(int i =0 ; i < num; i+=4)
{
*(v4sf*)&u[i] = *(v4sf*)&v[i] + *(v4sf*)&t[i];
//many other equations
}
}
float*u,*v,*t; //and many other variables
}
アプローチ 2:
アプローチ 1 と同じです。ただし、アプローチ 2 ではv
、 、u
、およびその他すべての変数が、配置を使用して、ヒープに事前に割り当てられた大きなチャンクに割り当てられますnew
。
typedef float v4sf __attribute__ (vector_size(16))
class Unit
{
public:
Unit(int num)
{
buffer = new char[num*sizeof(*u) + sizeof(*v) /*..and so on for other variables..*/]
u = new(buffer) float[num];
v = new(buffer+sizeof(float)*num) float[num];
//And so on for other variables
}
void update()
{
for(int i =0 ; i < num; i+=4)
{
*(v4sf*)&u[i] = *(v4sf*)&v[i] + *(v4sf*)&t[i];
//many other equations
}
}
char* buffer;
float*u,*v,*t; //and many other variables
}
ただし、アプローチ 2 は 2 倍高速です。何故ですか?
約 12 個の float 変数があり、num は 500K です。update() が呼び出され1k
ます。速度は、メモリ割り当てには影響しません。私はこのように速度を測定します:
double start = getTime();
for( int i = 0; i < 1000; i++)
{
unit->update();
}
double end = getTime();
cout<<end - start;
そして、これはアプローチ 2 で約 2 倍速くなります。
コンパイラ オプション:gcc -msse4 -o3 -ftree-vectorize.
L1 キャッシュは 256K、RAM は 8GB、ページサイズは 4K です。
編集: アプローチ 2 で変数を割り当てる際の間違いを修正しました。すべての変数は、異なるセクションに正しく割り当てられます。プロセッサは Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
編集: ここにソースを追加しました - Source。アプローチ 1) は 69.58 秒、アプローチ 2) は 46.74 秒です。2 倍高速ではありませんが、それでも高速です。