2Dボイドシミュレーションをどのように並列化できますか


16

異なるソース(クラスター、gpu)からの処理能力を使用できるように、2Dボイドシミュレーションをどのようにプログラムできますか。

ボイドの例

上記の例では、色の付いていない粒子は、クラスター化(黄色)して移動を停止するまで動き回ります。

問題は、左上のエンティティが右下のエンティティと相互作用する可能性は低いものの、すべてのエンティティが潜在的に相互作用する可能性があることです。ドメインが異なるセグメントに分割された場合、全体が高速化される可能性がありますが、エンティティが別のセグメントに移動したい場合は問題が発生する可能性があります。

現時点では、このシミュレーションは良好なフレームレートの5000のエンティティで機能しますが、可能であれば何百万ものエンティティで試してみたいと思います。

これをさらに最適化するために四分木を使用することは可能でしょうか?他の提案はありますか?


最適化を要求していますか、それとも並列化する方法ですか?これらは異なるものです。
bummzack

@bummzack並列化する方法、さらに説明を追加しましたが、助けになりますか?
サイクレン

回答:


7

Mattias Lindeによる修士論文のParticle Fluids of Particle Fluidsは、大規模シミュレーションのデータ分割とアルゴリズムに関する洞察を提供するかもしれません。

彼の論文はSmoothed-Particle Hydrodynamicsに向けられており、単純なソリューションでは、シミュレーションでパーティクルのカーネルフットプリントのサイズに近いバケットサイズのSpatial Hashingを使用する傾向があります。

一般的なSPHカーネルでは相互作用距離がハードクランプされているため、システムのスケールアップにはこのようなパーティション最適化がほぼ不可欠です。


素晴らしい論文ですが、この質問に関する実際の部分は、@ Fxlllの回答のようにたくさんあるようです。
Ali1S232

論文の実際の部分は、通信プロトコルを導入することによってエッジケースを解決する方法、ハード部分、クワッドパーティショニングはかなり明白であり、それ自体はエッジケースの問題を解決しないと思います。
マイクセンダー

4

ずっと前に学んだ用語は、ゲームの情報速度です。

あなたのboidの速度が1であり、彼らが隣人だけを気にしている場合、情報の速度は3です。つまり、あなたから2マス離れたboidは、1フレーム内であなたが気にする範囲内にあります。

インタラクションのボイドごとに1平方移動(1 + 1)に加えて、物に気付く距離(1)が3に等しい。

これを考えると、マップを必要なだけ小さなサイズに分割できることを学習しますが、この速度の情報により、隣接するすべてのチャンクに重なります。

私はあなたのボイドが1つの正方形だけを動かすことを許可していると仮定しますが、彼らは3つを見ることができます

大規模な並列シミュレーションを実行する場合は、10x10のグリッドに分割しますが、各エッジで5つの正方形が重なります。自分の1人がローカルチャンクのエッジから情報距離内にいるときはいつでも、隣接を更新する必要があり、境界を横断すると、それらは自分のものではなくなります。隣人が、彼らがコントロールしているボイドがあなたのチャンクに移動したと言ったら、あなたはそのAIを引き継がなければなりません。

つまり、通信は隣接するチャンクマネージャーにローカライズされ、トラフィックは最小限に抑えられます。実行するジョブが多いほど、より多くのCPUを使用してシミュレーションを実行できますが、実行するジョブが多いほど、それらのオーバーラップが多くなるため、シミュレーションの進行に応じてジョブ/チャンク間でやり取りされる情報が多くなります。これは、AIの複雑さと使用可能なハードウェアに基づいて、手に負けずにチャンクサイズを調整する必要がある場所です。


世界が1,000,000x1,000,000グリッドであり、世界に10,000,000のボイドがあり、各ボイドがターンごとに正確に1マスずつ移動できると想像してください。
Ali1S232

2000 500x500以上の正方形に分割できると思います。各正方形には、ボイドのリストと隣人のリストが含まれています。ボイドが正方形を出ると、ボイドのリストから削除され、他の正方形に追加されます。私が見ることができるこの方法の問題は、正方形よりも大きい群れをもつ何かを追加する場合です。クワッドツリーソリューションは動的である必要がありますが、それがどれほど高価かはわかりません
-Sycren

@Gajet:チャンク内のボイドまたは隣接する管理境界線のみをチェックする必要があります。境界線は、エンティティが移動できる距離に加えて、エンティティが見ることができる距離を考慮した設計によって保証されています。@Sycren:群れは、私たちには大きな存在であるように見えますが、それでも小規模な効果にすぎません。魚の群れは群れに従わず、観察可能な隣人に従います。
リチャードファビアン

2

クエリを読むことで、クワッドツリーを活用し、クワッドツリーを作成し、異なる処理ユニットで各セグメントのシミュレーションを実行できるようです。これにより、チェックは互いに近いオブジェクトに対してのみ行われます。ただし、サイクルごとにスレッドを同期する必要があります。つまり、これらのボイドの一部をある処理グループから別の処理グループに転送します。一般に、すべてのサイクルは3つのステップで構成されます。

  1. すべてのBoidを1ユニットずつ移動します。(複数のスレッドを使用して簡単に処理できます)
  2. 各ボイドをグループに割り当てます*。これは、O(n)のアルゴリズムを使用して、どのboidが衝突する可能性が最も高いかを選択する必要があることを意味します。これは、複数のスレッドを使用して処理することもできます。
  3. 最後に、同じグループ内の2つのボイドが衝突したかどうかを確認する必要があります。

*グループを作成するには、次のパターンを使用できます。

ここに画像の説明を入力してください

一部のボイドは複数のグループの一部である可能性がありますが、このパターンではより正確な結果が得られることに注意してください。このパターンを使用して必要な数のグループを作成することもできます。これは、ボイドの数と画面のサイズ、作成する必要があるグループの最適な数を見つけるために必要な数です。

-編集-

@LarsViklundの論文に記載されているセグメンテーションに関する別のアイデアがあります。この方法では、二重チェックがはるかに少なく、ステップ間でスレッド数を増減する必要がありません。

ここに画像の説明を入力してください

一部の領域はまだ2つのグループの一部であることに注意してください。そして両方のグループカバーの領域の幅は正確2*maximum speedです。あなたの場合、boidがシミュレーションステップごとに1ピクセル移動する場合、各2グループ間で2ピクセル幅の領域のみを共有する必要があります。そして4つのグループの一部である小さなエリアがあります。しかし、一般的にこのメソッドは実装が簡単で、正しく実装されている場合ははるかに高速です。ちなみに、この方法で逆方向に移動することはできません。何らかのオブジェクトが移動できる場合、それ以上移動する必要はありません。


良いアイデアのように聞こえますが、ステップ1に進む前に、衝突検出を実行して、移動できるかどうかを確認する必要がありますか?
サイクレン

シミュレーションを続行しない場合は、それらを移動して、その移動と逆の衝突が発生するかどうかを確認できます(その正確なボイドに対して)。
Ali1S232

ありがとう、それはもっと理にかなっています。クワッドツリーとは別に、ワークロードを分割する他の方法を考えることができますか?
サイクレン

ご覧のとおり、セグメンテーションは完全にクワッドツリーそのものではなく、正確性を高めるための追加のグループがもう1つあります。クアッドツリースタイルの方がはるかに簡単です。ワールドサイズに応じて、グループを追加できます。これにより、各サイクルでのチェックが少なくなります。メモリの消費と計算速度のトレードオフです。また、グループごとに必ずしも1つのスレッドである必要はありません。いくつかのスレッドで複数のグループを計算できます。グループ計算を2つ以上のスレッドに分割することもできます。
Ali1S232

@Gajetあなたの写真を正しく理解すれば、グループの重複する領域が非常に大きいため、二重の計算がたくさんあります。質問が最大数百万ポイントをシミュレートすることを要求することを考えると、それは大きな無駄です。
マイクセンダー

2

私は最近、これらの回答のいくつかを出発点としてこの問題に取り組みました。覚えておくべき最も有用なことは、ボイドは一種の単純なn体シミュレーションであるということです。各ボイドは、隣接する物体に力を及ぼす粒子です。

Lindeの論文は読みにくいと感じました。代わりに、SJプリンプトンの「短距離分子動力学のための高速並列アルゴリズム」を参照することをお勧めします。Plimptonの論文は、より読みやすく詳細な図で詳細に記載されています。

一言で言えば、原子分解法は原子のサブセットを各プロセッサに永久に割り当て、力分解法はペアワイス力計算のサブセットを各プロシージャに割り当て、空間分解法はシミュレーションボックスのサブ領域を各プロシージャに割り当てます。 。

ADを試すことをお勧めします。理解して実装するのが最も簡単です。FDは非常に似ています。FDを使用したCUDAを使用したnVidiaのnボディシミュレーションを次に示します。これにより、タイリングとリダクションがどのようにシリアルパフォーマンスを大幅に上回るかをおおまかに理解できます。

SDの実装は一般に最適化手法であり、実装するにはある程度の振り付けが必要です。彼らはほとんど常により速く、より良いスケーリングです。

これは、AD / FDが各Boidの「隣接リスト」を構築する必要があるためです。すべてのboidがその近傍の位置を知る必要がある場合、それらの間の通信はO(n ²)。あなたはすべてのステップのすべてのいくつかのタイムステップの代わりにリストを再構築することを可能にする地域ごとBOIDチェックのサイズを小さくするためにVerletの隣接リストを使用することができますが、それはまだO(だN ²)。SDでは、各セルに隣接リストが保持されますが、AD / FDではすべてのボイドに隣接リストがあります。したがって、すべてのboidが互いに通信する代わりに、すべてのセルが互いに通信します。通信速度の低下は、速度の向上の原因です。

残念ながら、ボイドの問題はSDをわずかに妨害します。各プロセッサがセルを追跡することは、ボイドが領域全体にある程度均等に分散している場合に最も有利です。しかし、あなたしたいクラスタ一緒にboidsを!群れが適切に動作している場合、プロセッサの大部分は刻々と過ぎて空のリストを相互に交換し、セルの小さなグループはADまたはFDと同じ計算を実行します。

これに対処するには、セルのサイズ(定数)を数学的に調整して、任意の時点で空のセルの数を最小限に抑えるか、クアッドツリーにBarnes-Hutアルゴリズムを使用します。BHアルゴリズムは非常に強力です。逆説的に、並列アーキテクチャに実装することは非常に困難です。これは、BHツリーが不規則であるため、並列スレッドが大幅に変化する速度でツリーを横断するため、スレッドの発散が発生するためです。SalmonとDubinskiは、直交再帰二分法アルゴリズムを提示して、プロセッサ間でクアッドツリーを均等に分散しました。これは、ほとんどの並列アーキテクチャで繰り返し修正する必要があります。

ご覧のとおり、この時点で明らかに最適化と黒魔術の領域にいます。繰り返しになりますが、Plimptonの論文を読んで、それが意味をなすかどうかを確認してください。


1

私はあなたのものがトロイダルシステムであると仮定しています、あなたは各ユニットがそのサブエリアを持つようにスペースに分割できます。

パーティクルが移動する各ステップで、サブエリアから出るパーティクルは関連するプロセッサに送信されます。通信ステップはプロセッサーを同期させ、最後のポストステップが行われ、異物の位置(存在する場合)を詳述します。

ここには3つの問題があります。

  • 1)サブエリアの形状:

長方形を選択することもできますが、サークルと比べて面積/周囲比が小さくなっています。境界線が大きいほど、より多くのパーティクルが残ります。シクルは最高のA / p比を示しますが、テッセレーションには使用できません。そのため、いくつかの(場合によっては半規則的な)テッセレーションに平均A / p比の良い値を設定する必要があります。明らかにセル座標によるタッセルインデックスの計算は簡単なはずなので、非常にエキゾチックなタッセレーションを試す前にこれを考慮してください。

  • 2)通信プロトコル:

使用している通信インフラストラクチャの種類に応じて、プロセッサ間で国境を越える情報を分散させる方法を考えることができます。ブロードキャスト対ピアツーピア再構築対ピアツーピア通信はすべてオプションです。

  • 3)サブエリアの割り当て:

各ステップで同期が行われるため、精緻化のバランスを保つ必要があります。プロセッサーに領域を静的または動的に割り当てることを選択できます。あなたのスペースがアクティブなパーティクルで不自然に覆われている場合、これは大きな問題ではありませんが、衝突がパーティクルを非アクティブ化するため、この場合は真実ではない可能性があります。割り当てを変更するには、より重い通信ステップが必要です; すべてのプロセッサが国境を越えた情報を共有している場合、いくつかのショートカットをとることができますが、それについていくつかの検討を行う必要があります


@Fxlllドーナツの形ではなく、トロイダルシステムの意味がわかりません。粒子が右側から外れると、左側に再び現れるということですか?そうでない場合、粒子が右側に当たると、別の方向に移動しようとします。
サイクレン

@Sycren OKこの場合、特別な方法でタッセレーションとエッジの領域を処理するためにいくつかの検討を行う必要があります
-FxIII

-1

手がかりを得るためにシミュレーションを試してくださいhttps://github.com/wahabjawed/Boids-Simulation

これをXNAで開発しました


完全なプロジェクトにリンクするだけでは良い答えではありません。読者は質問に関連する部分を見つけるまであなたのソースを掘り下げることを余儀なくされ、それでも問題を解決する方法を理解する必要があります。問題にどのようにアプローチしたか、また他の回答で説明されている解決策と比べてどのような利点があるか、わかりやすい英語で説明していただけますか?説明の理解に役立つ場合は、短いコードスニペットをコピーして回答に貼り付けることができます。
フィリップ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.