オブジェクト指向プログラミング (OOP) ソリューションとボールの束を更新するデータ指向設計 (DOD) ソリューションを比較するサンプル コードを次に示します。
const size_t ArraySize = 1000;
class Ball
{
public:
float x,y,z;
Ball():
x(0),
y(0),
z(0)
{
}
void Update()
{
x += 5;
y += 5;
z += 5;
}
};
std::vector<Ball> g_balls(ArraySize);
class Balls
{
public:
std::vector<float> x;
std::vector<float> y;
std::vector<float> z;
Balls():
x(ArraySize,0),
y(ArraySize,0),
z(ArraySize,0)
{
}
void Update()
{
const size_t num = x.size();
if(num == 0)
{
return;
}
const float* lastX = &x[num - 1];
float* pX = &x[0];
float* pY = &y[0];
float* pZ = &z[0];
for( ; pX <= lastX; ++pX, ++pY, ++pZ)
{
*pX += 5;
*pY += 5;
*pZ += 5;
}
}
};
int main()
{
Balls balls;
Timer time1;
time1.Start();
balls.Update();
time1.Stop();
Timer time2;
time2.Start();
const size_t arrSize = g_balls.size();
if(arrSize > 0)
{
const Ball* lastBall = &g_balls[arrSize - 1];
Ball* pBall = &g_balls[0];
for( ; pBall <= lastBall; ++pBall)
{
pBall->Update();
}
}
time2.Stop();
printf("Data Oriented design time: %f\n",time1.Get_Microseconds());
printf("OOB oriented design time: %f\n",time2.Get_Microseconds());
return 0;
}
さて、これはVisual Studioでコンパイルして実行しますが、これを行うことが許可されているかどうか疑問に思っていますが、これを確実に行うことができるはずです:
const float* lastX = &x[num - 1];//remember, x is a std::vector of floats
float* pX = &x[0];//remember, x is a std::vector of floats
float* pY = &y[0];//remember, y is a std::vector of floats
float* pZ = &z[0];//remember, z is a std::vector of floats
for( ; pX <= lastX; ++pX, ++pY, ++pZ)
{
*pX += 5;
*pY += 5;
*pZ += 5;
}
私の理解では、 std::vector のデータは連続しているはずですが、これが別のプラットフォームで問題になるかどうか、標準に違反するかどうか、内部でどのように保存されているかはわかりません。また、これは私が DOD ソリューションを OOP ソリューションよりも優れたものにすることができた唯一の方法であり、反復の他の方法はそれほど良くありませんでした。イテレータを使用することもできますが、最適化が有効になっている、別名リリース モードの OOP よりも高速であると確信しています。
それで、これは DOD を行う良い方法ですか (最善の方法ですか?)、これは正当な c++ ですか?
[編集] さて、国防総省の場合、これは悪い例です。x、y、z は Vector3 にパッケージ化する必要があります。したがって、DOD は OOP よりもデバッグで高速に実行されましたが、リリースでは別の話でした。繰り返しますが、これは DOD を効率的に使用する方法の悪い例ですが、同時に多数のデータにアクセスする必要がある場合は短所であることを示しています。DODを使いこなすコツは、「アクセスパターンに基づいたデータ設計」です。