データ指向設計とは何ですか?


156

私はこの記事を読んでいて、この人は、データ指向のデザインとOOPを組み合わせることで誰もがどのように大きな利益を得ることができるかについて話し続けました。ただし、コードサンプルは表示されません。

私はこれをグーグルで調べたところ、コードサンプルはもちろんのこと、これが何であるかについての実際の情報を見つけることができませんでした。誰かがこの用語に精通しており、例を提供できますか?これは別の言葉かもしれませんか?


7
ゲーム開発者の記事がブログ形式で読みやすくなりました。gamesfromwithin.com
oriented

58
何かをグーグルで検索し、ターゲットを絞ったすばらしいSOの質問を見つけて、それが何年も前に質問したのがあなただと気付いたことがありますか?
ryeguy 2013年


14
@ryeguy、私は質問をし、ググって、素敵なSOの質問を見つけ、それから私何年も前に答えたことに気づきました。
Michael Deardeuff 2014

4
私は何かをグーグルで検索し、素晴らしいSOの質問を見つけました。質問も回答も私ではありませんでした:)
Nadjib Mami

回答:


287

まず、これをデータ駆動型設計と混同しないでください。

データ指向設計についての私の理解は、効率的な処理のためにデータを編成することについてです。特にキャッシュミスなどに関しては、データドリブンデザインとは、プログラムの多くの動作をデータに制御させることです(Andrew Keithの回答で非常によく説明されています)。

アプリケーションに、色、半径、弾力、位置などのプロパティを持つボールオブジェクトがあるとします。

オブジェクト指向アプローチ

OOPでは、ボールを次のように記述します。

class Ball {
  Point  position;
  Color  color;
  double radius;

  void draw();
};

そして、次のようなボールのコレクションを作成します。

vector<Ball> balls;

データ指向のアプローチ

ただし、データ指向設計では、次のようなコードを書く可能性が高くなります。

class Balls {
  vector<Point>  position;
  vector<Color>  color;
  vector<double> radius;

  void draw();
};

ご覧のとおり、1つのボールを表す単一のユニットはもうありません。Ballオブジェクトは暗黙的にのみ存在します。

これには、パフォーマンスに関して多くの利点があります。通常、多くのボールを同時に操作したいと考えています。ハードウェアは通常、効率的に動作するためにメモリの大きな連続したチャンクを必要とします。

次に、ballsプロパティの一部にのみ影響する操作を実行する場合があります。たとえば、すべてのボールの色をさまざまな方法で組み合わせる場合は、キャッシュに色情報のみを含める必要があります。ただし、すべてのボールプロパティが1つのユニットに格納されている場合、ボールの他のすべてのプロパティも同様に取得します。あなたはそれらを必要としませんが。

キャッシュの使用例

各ボールが64バイトを使用し、1ポイントが4バイトを使用するとします。キャッシュスロットは、例えば、64バイトもかかります。10個のボールの位置を更新する場合は、10 * 64 = 640バイトのメモリをキャッシュに取り込み、10回のキャッシュミスを取得する必要があります。ただし、ボールの位置を個別のユニットとして処理できる場合、4 * 10 = 40バイトしかかかりません。これは1つのキャッシュフェッチに収まります。したがって、10個のボールすべてを更新するために1回のキャッシュミスしか得られません。これらの数値は任意です-キャッシュブロックが大きいと思います。

ただし、メモリレイアウトがキャッシュヒットに深刻な影響を与え、パフォーマンスにどのように影響するかを示しています。これは、CPUとRAMの速度の違いが大きくなるにつれて、ますます重要になります。

メモリのレイアウト方法

ボールの例では、通常、通常のアプリでは複数の変数に一緒にアクセスする可能性が高いため、問題を大幅に簡略化しました。たとえば、位置と半径はおそらく一緒に頻繁に使用されます。次に、構造は次のようになります。

class Body {
  Point  position;
  double radius;
};

class Balls {
  vector<Body>  bodies;
  vector<Color>  color;

  void draw();
};

これを行う必要があるのは、一緒に使用されるデータが別々のアレイに配置される場合、それらがキャッシュ内の同じスロットで競合するリスクがあるためです。したがって、一方をロードすると他方がスローされます。

したがって、オブジェクト指向プログラミングと比較すると、最終的に作成するクラスは、問題のメンタルモデルのエンティティとは関係ありません。データはデータの使用に基づいてまとめられるため、データ指向の設計でクラスに付ける適切な名前が常にあるとは限りません。

リレーショナルデータベースとの関係

データ指向設計の背後にある考え方は、リレーショナルデータベースについての考え方と非常に似ています。リレーショナルデータベースの最適化では、キャッシュをより効率的に使用することもできますが、この場合、キャッシュはCPUキャッシュではなく、メモリ内のページです。また、優れたデータベース設計者は、アクセス頻度の低いデータを別のテーブルに分割する可能性が高く、数列しか使用されていないテーブルを大量に作成するのではなく、また、ディスク上の複数の場所からデータにアクセスする必要がないように、いくつかのテーブルを非正規化することを選択する場合もあります。データ指向設計の場合と同様に、これらの選択は、データアクセスパターンとは何か、パフォーマンスのボトルネックはどこにあるかを調べることによって行われます。


4
これをありがとう、あなたはそれをとてもよく説明しました。
ryeguy

4
よく言った 質問は1つだけです。struct balls {vector<vec3> pos; vector<vec3> velocity;}速度ベクトルと位置ベクトルの間で前後に移動するため、各ボールの位置を実際に更新していない構造があるとします(最新のマシンとキャッシュラインなどすべて、これはイラストも)
falstro

14
かもしれない。ただし、pos配列全体が一度に読み込まれることはありません。キャッシュラインが1つだけで、一部のプリフェッチが可能です。同様に速度で。したがって、それらを相互にトラッシュするには、対応するposおよびvectorの各チャンクを同じキャッシュラインにマップする必要があります。もちろんそれは起こり得ます。そのため、一緒に使用される変数を構造体にまとめることが推奨されています。したがって、たとえば、速度と位置は1つのベクトルにあり、色は別のベクトルにあります。
Erik Engheim、2010

1
@roe一緒にアクセスされるプロパティをグループ化する必要があります。プロパティ間の依存関係はまったくないはずです。したがって、この構造の方が優れていstruct balls { vector<color> colors; vector<body> bodies; /* contains position and velocity */ }ます。
ダニジャー2013

2
@danijar私はあなたの提案で説明を更新しました。私はこれについてもっと多くのことを言うことができたかもしれませんが、それは本当に記事に変わるだけです。
Erik Engheim 2014

18

Mike Actonは最近、データ指向設計について公開講演しました。

私の基本的な要約は次のとおりです。パフォーマンスが必要な場合は、データフローについて考え、ねじ込み、最適化する可能性が最も高いストレージレイヤーを見つけますマイクはリアルタイムで行うため、L2キャッシュミスに焦点を当てていますが、データベース(ディスク読み取り)やWeb(HTTPリクエスト)にも同じことが当てはまると思います。これはシステムプログラミングを行うのに便利な方法だと思います。

アルゴリズムや時間の複雑さについて考えるのをやめないことに注意してください。それは、マッドCSスキルでターゲットにする必要がある最も高価な操作タイプを理解することに集中するだけです。


14

Noelがゲーム開発で直面している特定のニーズについて具体的に話していることを指摘したいだけです。リアルタイムソフトシミュレーションを実行している他のセクターがこれから利益を得ると思いますが、一般的なビジネスアプリケーションに顕著な改善を示すテクニックになるとは思えません。この設定は、パフォーマンスの最後のすべてのビットが基盤となるハードウェアから確実に排除されるようにするためのものです。


同意した。データ指向の設計が重要となる他のいくつかの領域は次のとおりです。高帯域幅デバイス用のハードウェアとファームウェア(ネットワークやストレージなど)。大規模な科学計算(例:気象シミュレーション、タンパク質のフォールディング)、信号処理(例:オーディオ、画像、ビデオ)、データ圧縮。これらは、より一般的なコンピュータサイエンスとは別のメジャーとして提供されることがある「計算科学とエンジニアリング」に分類されます。
rwong 2013

-3

データ指向設計とは、アプリケーションのロジックが、手続き型アルゴリズムではなく、データセットで構築される設計です。例えば

手続き型アプローチ。

int animation; // this value is the animation index

if(animation == 0)
   PerformMoveForward();
else if(animation == 1)
  PerformMoveBack();
.... // etc

データ設計アプローチ

typedef struct
{
   int Index;
   void (*Perform)();
}AnimationIndice;

// build my animation dictionary
AnimationIndice AnimationIndices[] = 
  {
      { 0,PerformMoveForward }
      { 1,PerformMoveBack }
  }

// when its time to run, i use my dictionary to find my logic
int animation; // this value is the animation index
AnimationIndices[animation].Perform();

このようなデータ設計は、アプリケーションのロジックを構築するためのデータの使用を促進します。特に、アニメーションやその他の要因に基づいて何千ものロジックパスを持つ可能性のあるビデオゲームでは、管理が容易です。


14
これは実際には正しくありません。データ指向の設計とデータ指向の設計を混同しています。Noelの記事を読んで、彼がまったく違うことについて話していることに気づくまで、私は同じことをしました。
Erik Engheim、2010年

12
また、Indiceは言葉ではありません。「インデックス」と「インデックス」があり、「インデックス」を容認するものもありますが、「インデックス」は正しくありません。
Baxissimo 2011年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.