10

ニュートンの法則に従って空間を移動する一連の N 個の粒子の (同時) シミュレーターを構築しています。私の考えは、各粒子をタスクとしてモデル化することです。タスクは、他の粒子 (タスク) と相互作用して、その位置と質量を取得し、それが受ける正味の力を計算します。各粒子タスクは次のようなものです

while(true){
   force = thisParticle.calculateNetForce(allTheParticles);
   thisParticle.waitForAllTheParticlesToCalculateNetForce(); // synchronization
   thisParticle.updatePosition(force);
   thisParticle.waitForAllTheParticlesToUpdateTheirState(); // synchronization
}

多くのパーティクル (100 以上) を持つことができるので、そのような数の Java スレッド (物理スレッドにマップされる) を作成することはできません。私の考えはRuntime.getRuntime().availableProcessors()+1、多くのタスクを実行できるスレッドを使用することです。

ただし、粒子タスクが終了しないため、FixedThreadExecutor を使用できません。内部で一種のスケジューリングも実行できる必要がある FixedThreadExecutor を使用したいと思います。この目的のために何か知っていますか?

または、並行性の観点からそのようなシステムをモデル化するためのより良いアプローチを提案してもらえますか (たとえば、別のタスクの分割)。

Ps: 私は「古典的な」同時実行メカニズムに限定されており、アクターや同様のアーキテクチャは含まれていません。

4

7 に答える 7

1

離散的なステップで計算してみませんか?

while(true){


for(Particle p : allParticles){
   force = p.calculateNetForce(allParticles);   
   p.setNextPosition(force); //Remembers, but doesn't change the current position
}

for(Particle p : allParticles){
    p.nextState(); //Change the position
}

}

最初に各パーティクルの力を計算しますが、現在の状態は変更しないでください。すべての粒子について計算したら、以前の計算に従って内部状態を更新します。このように、単一のスレッドでも十分です。もちろん、計算を複数のスレッドに分割できますが、追加の同期が必要になります

Java 8 アップデート

Java 8 を使用すると、スレッドや同期などを気にする必要がなく、マルチコア システムを利用できます。

 while(true){
       allParticles.parallelStream().forEach(p -> {
           double force = p.calculateNetForce(allParticles);
           p.setNextPosition(force)
       });

       allParticles.parallelStream().forEach(p ->   p.nextState());      
 }
于 2013-08-05T14:17:48.697 に答える
1

粒子ごとに を呼び出しますcalculateNetForce(allTheParticles)。これにより、計算が O(N^2) (すべての粒子の数の 2 乗) に比例すると思います。これは主なパフォーマンス キラーであり、O(N) の複雑さを持つアルゴリズムを見つけてから、並列化を試みることをお勧めします。頭のてっぺんから、すべての粒子の総質量と重心を最初に計算することを提案できます。次に、各粒子について、残りの粒子の質量と中心を計算します。これは、総質量と中心を取得し、現在の粒子の代わりに負の質量を持つ「穴」を追加することで実行できます。次に、粒子と残りの部分の間の力を計算します。各粒子の計算は独立しており、他のコメンターによって提案された方法のいずれかと並列化できます。

于 2013-08-23T16:30:14.210 に答える