1

私は宇宙の惑星のシミュレーターを作成していますが、問題は、シミュレーションが指数関数的に遅くなるため、100を超える惑星をシミュレートできないことです。この問題を解決するために、私はおそらくグラフィックカードプロセッサを使用して計算するのに十分な経験がないので、スレッドを使用することで問題を解決できると思いました。

私のプログラムには2つの関数があり、惑星間の重力を計算するために使用され、もう1つは衝突をチェックするために使用されます。ある方法でスレッドを実装したので、あるスレッドで重力を計算し、別のスレッドで衝突を計算します。

問題は、スレッドを使用しない場合よりもシミュレーションが高速に実行されないことです。多分私はそれらを間違って実装していますか?

int main()
{
    int numOfPlanets;
    cout << "Enter the maximum number of planets to generate: ";
    cin >> numOfPlanets;
    App.Create(sf::VideoMode(1366, 740), "SFML Galaxy Simulator");
    App.Clear(sf::Color(20,20,20));

    generateRandomPlanets(500, 500, numOfPlanets);
    //createPlanet(planets, sf::Vector2f(500,500), sf::Vector2f(0,0), 5, 500);

    thread thread_1;
    thread thread_2;


    while(App.IsOpened())
    {
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }

        App.Clear(sf::Color(20,20,20));
        thread_1 = thread(checkCollision);
        thread_2 = thread(calculateForce);
        thread_1.join();
        thread_2.join();
        updatePlanets();
        App.Display();
    }
    thread_2.join();
    thread_1.join();
    return 0;
}
4

2 に答える 2

2
    thread_1 = thread(checkCollision);
    thread_2 = thread(calculateForce);
    thread_1.join();
    thread_2.join();
    updatePlanets();

これにより、2つの新しいスレッドが起動され、いくつかの作業が並行して実行され、それらが終了するのを待ってブロックされ、その後実行されupdatePlanetsます。あなたはおそらく欲しい:

    thread_1 = thread(checkCollision);
    thread_2 = thread(calculateForce);
    updatePlanets();
    thread_1.join();
    thread_2.join();

これにより、3つの機能が並行して実行されます。

また、これは最後のエラーですmain

thread_2.join();
thread_1.join();
return 0;

すでにスレッドに参加しているので、再度参加することはできません。

実際には、ループの外で宣言しthread_1thread_2再利用する意味はありません。ループ内で宣言するだけで済みます。

    thread thread_1(checkCollision);
    thread thread_2(calculateForce);
    updatePlanets();
    thread_1.join();
    thread_2.join();

またupdatePlanets、例外をスローするとthread_2、スレッドが参加可能である間にデストラクタが実行されるため、プログラムが終了することに注意してくださいterminate()。このプログラムでは問題ない可能性がありますが、注意が必要です。

于 2013-03-06T20:35:44.207 に答える
1

質問を投稿した後、さらに調査を行ったところ、シミュレーションのパフォーマンスにおける主な問題は、他のすべての惑星と比較した各惑星の重力を計算するためのアルゴリズムの時間計算量であることがわかりましたO(n^2)

これにアプローチするための1つまたはおそらく最良の方法は、時間計算量がのn体シミュレーションにBarnes-HutO(n log n)アルゴリズムを使用することであることがわかりました。このアルゴリズムが機能する方法は、すべての惑星を四分木ノードに分割し、各ノードの重心に応じて力を計算することです。

したがって、これらすべてを足し合わせるには、バーンズハットアルゴリズムをスレッド化と一緒に使用することが、この問題に取り組むための最良の方法です。

于 2013-03-07T14:15:13.203 に答える