質問

この記事を読んでいたのですが、この男は誰もがどのように大きな利益をもたらすかについて話し続けていますデータ指向設計とOOPの混合から。ただし、コードサンプルは表示されません。

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

役に立ちましたか?

解決

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

データ指向設計の私の理解は、効率的な処理のためにデータを整理することです。特にキャッシュミスなどに関しては、データドリブンデザインは、データがプログラムの動作の多くを制御できるようにすることです(アンドリューキースの回答)。

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

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

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つのボールを表す単一のユニットはもうありません。ボールオブジェクトは暗黙的にのみ存在します。

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

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

キャッシュの使用例

各ボールが64バイトを占有し、ポイントが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キャッシュではありません。また、優れたデータベース設計者は、使用頻度の低いデータを別のテーブルに分割する可能性があります。これは、少数の列しか使用されなかった膨大な数の列を持つテーブルを作成するためです。また、ディスク上の複数の場所からデータにアクセスする必要がないように、いくつかのテーブルを非正規化することも選択できます。データ指向設計の場合と同様に、これらの選択は、データアクセスパターンが何であるか、そしてどこで

他のヒント

マイクアクトンが最近データ指向設計について公開講演を行いました:

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

アルゴリズムと時間の複雑さについて考えることからあなたを解放するわけではないことに注意してください、それはあなたがあなたの狂ったCSスキルでターゲットにしなければならない最も高価な操作タイプを見つけることにあなたの注意を集中します。

ノエルは、ゲーム開発で直面している特定のニーズについて具体的に話していることを指摘したいと思います。リアルタイムのソフトシミュレーションを行っている他のセクターはこれの恩恵を受けると思いますが、一般的なビジネスアプリケーションに顕著な改善を示す技術ではないでしょう。この設定は、パフォーマンスのすべての最後の部分が基礎となるハードウェアから絞り出されることを保証するためのものです。

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

手続き的アプローチ。

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();

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top