問題タブ [data-oriented-design]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 関数ポインターを使用してifステートメントをカットする方が効率的ですか?
したがって、if
繰り返しの多いループからステートメントを引き出すための次のルールがあります。
彼らは、ifステートメントを外に出すためにそれを分割する方が良いと言います:
(「Ho!自分で最適化しないでください!コンパイラが実行します!」と言っている場合)確かに、オプティマイザがこれを実行する可能性があります。しかし、Typical C ++ Bullshit (仮想関数に対する彼の態度など、彼のすべての点に同意しません)で、 MikeActonは次のように述べています。
では、代わりに関数ポインタを使用してみませんか?
関数ポインタに何らかの隠れたオーバーヘッドがありますか?ストレート関数を呼び出すのは効率的ですか?
c++ - OOPでのデータ指向設計
このスライド (スライド15の後)では、使用することをお勧めします
キャッシュ効率が高いからです。
クラスがある場合はどうですか
そして、そのクラスのすべてのオブジェクトを単一の線形配列に格納します。
それらはすべて同じアレイにあるので、キャッシュミスはありますか?なぜ最初のアプローチが優れているのでしょうか?
performance - オブジェクト指向、データ指向、キャッシュ汚染、キャッシュ自明性
通常のオブジェクト指向の慣行では、まれなオブジェクトが複数の無関係なメンバー プロパティを持つことはありません。また、オブジェクトが処理されている場合、それらのプロパティのさまざまな部分を対象とするさまざまなパスで処理が行われることも珍しくありません。
この点で、オブジェクトのコレクションを作成する典型的なアプローチは、あまり効率的ではないようです。コンピュータがメモリにアクセスする方法とキャッシュ ラインの平均サイズを考慮すると、キャッシュ メモリが不要なものでいっぱいになる可能性が非常に高くなりますが、たまたま隣接しているだけなので、キャッシュの容量が浪費され、ストールが追加されます。そして実行までの待ち時間。
さらに悪いのは、メモリ プールやカスタム アロケータを使用せずに、ポリモーフィズムを使用してオブジェクトを動的に割り当てる慣行です。この場合、キャッシュが不要なデータでいっぱいになるだけでなく、動的メモリ割り当てによって使用される任意のアドレスが原因で、プリフェッチャーも適切に機能しなくなります。
救いは、OOP以前の時代に戻ってデータ指向を選択することです。これは、パフォーマンスが重要なアプリケーション、オペレーティングシステムなどの開発の好みの選択であるようです. しかし、なぜこの 2 つのハイブリッド バージョンを使用しないのでしょうか。データ指向オブジェクトプログラミングの一種?
長い序曲の後、当面の問題に取り掛かりましょう。私はこの概念の効率をテストするのに十分な大規模なプロジェクトを持っていないので、コミュニティの理論的な専門知識は大歓迎です.
オブジェクトが独自のデータ メンバーを格納するのではなく、コレクションへの参照のみを格納し、データ メンバーが独自のコンテナーに順番に格納され、メンバー メソッドがそれらのコンテナーからデータを返すようにすると、不要なデータが終了する可能性がなくなります。 CPU に到達するまでの時間を減らす必要があり、近い「将来」に必要なデータの可能性が高くなります。論理的な前提として、このアプローチはプリフェッチャーの効率、キャッシュ ヒット、および使用効率を改善し、自動および手動の並列化に関連するレイテンシも削減します。
どう思いますか?
後半の編集:「データ指向パターン」の適用は、構造体とクラスのパディングを考慮に入れるとさらに有益になる可能性があります。「モデル」にデータメンバーchar
とint
データメンバーがある場合、OOP 方式でパディングされ、汚染するだけです。さらにキャッシュしますが、データ指向のストレージ モードではchar
、すべての とすべてint
の を順番に格納でき、スペースもキャッシュもまったく無駄になりません。
data-oriented-design - 継続的な割り当てでオブジェクトの削除を処理する方法は?
私は最近、データ指向設計の利点を発見しました。とても印象的です。ポイントの 1 つは、タイプとアクセスごとにデータをグループ化することです。すべてをオブジェクトにまとめるのではなく、配列にまとめて、キャッシュ ミスを防ぎ、処理を改善します。
そのため、ゲームではまだインスタンスがあり、ユーザーはそれらのいずれかを破棄できます (配列内に残るだけではありません)。配列の途中でオブジェクトの削除を効果的に処理する方法がわかりません。
私には 1 つの考えがあります:isAlive
値を持つことですが、すべてのオブジェクトが処理、描画などで何度もチェックされるため、多くの条件に非常に大きな影響を与えます...
もう 1 つのアイデアは、削除する必要があるスペースを埋めるために配列全体をシフトすることですが、これは削除時に多くのリソースを消費します。
DODでこれをどのように処理できますか?
したがって、要件を提示します。
- DOD で説明されているキャッシュ ミスを減らすには、配列にする必要があります。
- 高速なランダム位置オブジェクトの削除が必要です。最大 o(log n)
- オブジェクトは作成されてから移動できません。不明な場所で参照される可能性があるため、プログラムの誤動作を引き起こす可能性があります
c++ - 複数のインデックス付きデータ配列へのデータ指向アクセス
ゲーム エンジンのエンティティ コンポーネント システムに取り組んでいます。私の目標の 1 つは、最適なデータ処理のためにデータ指向のアプローチを使用することです。言い換えれば、構造体の配列よりも配列の構造体が欲しいというガイドラインに従いたいのです。ただし、私の問題は、これを解決するためのきちんとした方法を見つけることができなかったことです。
これまでの私の考えでは、システム内のすべてのコンポーネントがゲームロジックの特定の部分を担当し、重力コンポーネントが質量、速度などに応じてフレームごとに力を計算し、他のコンポーネントが他のものを処理するとします。したがって、すべてのコンポーネントは異なるデータセットに関心があります。重力コンポーネントは質量と速度に関心があるかもしれませんが、衝突コンポーネントはバウンディング ボックスと位置などに関心があるかもしれません。
これまでのところ、属性ごとに 1 つの配列を保存するデータ マネージャーを使用できると考えました。つまり、エンティティには、重量、位置、速度などの 1 つ以上があり、一意の ID を持つとします。データ マネージャーのデータは次のように表されます。ここで、すべての数字はエンティティ ID を表します。
このアプローチは、すべてのエンティティがそれぞれの属性を持っている場合にうまく機能します。ただし、エンティティ 0 と 2 のみがすべての木の属性を持ち、他のエンティティが移動しないタイプのエンティティである場合、それらには速度がなく、データは次のようになります。
突然、それを反復するのは簡単ではありません。反復処理と速度の操作のみに関心のあるコンポーネントは、2 番目のアプローチで行った場合、何らかの方法で空のギャップをスキップする必要があります。配列を短くする最初のアプローチは、より複雑な状況ではうまく機能しません。3 つの属性すべてを持つ 1 つのエンティティ 0、重量と位置のみを持つ別のエンティティ 1、位置と速度のみを持つエンティティ 2 があるとします。最後に、重みだけを持つ最後のエンティティ 3 が 1 つあります。押しつぶされた配列は次のようになります。
他のアプローチでは、次のようなギャップが残ります。
これらの状況はどちらも、少数の属性しか持たないエンティティーのセットを反復することにのみ関心がある場合、反復するのは自明ではありません。特定のコンポーネント X は、たとえば位置と速度を持つエンティティの処理に関心があります。反復可能な配列ポインタを抽出して、このコンポーネントに計算を実行させるにはどうすればよいですか? 要素が隣り合っている配列を指定したいのですが、それは不可能に思えます。
私は、すべての配列にビットフィールドを用意し、どのスポットが有効で、どのスポットがギャップであるかを記述する、または穴のない一時的な配列にデータをコピーしてからコンポーネントに与えるシステムなどのソリューションについて考えてきました。アイデアはありましたが、私が考えたものはエレガントではなく、処理のための追加のオーバーヘッドがありませんでした (データが有効かどうかの追加のチェック、またはデータの追加のコピーなど)。
誰かが似たような経験をしたり、この問題を追求するのに役立つアイデアや考えを持っていることを願っているので、ここで質問しています. :) また、このアイデア全体がくだらないものであり、正しく理解することが不可能であり、代わりにもっと良いアイデアがある場合は、教えてください. 質問が長すぎたり、雑然としたりしないことを願っています。
ありがとう。
c++ - データ指向設計では型にメソッドを持たせる必要がありますか?
現在、私のアプリケーションは 3 種類のクラスで構成されています。データ指向の設計に従う必要があります。そうでない場合は修正してください。以上が3種類のクラスです。コード例はそれほど重要ではありません。必要に応じてスキップできます。彼らはただ印象を与えるためにそこにいます。私の質問は、型クラスにメソッドを追加する必要があるかどうかです。
現在のデザイン
型は値を保持しているだけです。
モジュールは、それぞれ 1 つの特徴的な機能を実装します。それらはグローバルに保存されているため、すべてのタイプにアクセスできます。
マネージャーModule
は、基本クラスを介してモジュールに挿入される一種のヘルパーです。上記で使用されEntity
ているのは、エンティティ マネージャーのインスタンスです。他のマネージャーは、メッセージング、ファイル アクセス、SQL ストレージなどを扱います。つまり、モジュール間で共有する必要があるすべての機能です。
それに問題がある
これで、私の現在のデザインのアイデアが得られました。ここで、型がより複雑な初期化を必要とする場合を考えてみましょう。たとえば、Model
タイプはテクスチャと頂点バッファの OpenGL ID を格納しただけです。実際のデータは、事前にビデオ カードにアップロードする必要があります。
現在、モデルのセットアップを処理Models
する関数を備えたモジュールがあります。Create()
しかし、この方法では、他のモジュールからではなく、このモジュールからのみモデルを作成できます。Model
これを複雑化しながら型クラスに移動する必要がありますか? 以前は、型定義を単なるインターフェースと考えていました。