要するに:
シングル コアでマルチスレッド アプリを実行すると、どのようなシナリオでパフォーマンスが低下する可能性がありますか?
マルチスレッド アプリのアフィニティを 1 つのコアのみを使用するように設定するのはどうですか?
長文:
独自のスレッドで 2D エンジンの物理演算を実行しようとしています。それは機能し、最初はパフォーマンスが正常に見えましたが、ゲームを 10K FPS で実行し、物理を 120FPS で実行するように指示し、タスク マネージャーに移動して、プログラムが 1 つのコアのみを使用できるようにアフィニティを設定しました。
FPS は、アフィニティを 1 つのコアに設定する前は ~1700 でしたが、その後は ~70FPS になりました。こんなに減るとは思わなかった。私は、ゲームを 300 FPS で実行し、物理演算を 60 FPS で実行するように指示しました。
同じことが起こりました。
あまり考えていなかったので、エンジンの改造を続けました。描画コードの一部を 300 FPS、物理演算用に 60FPS に変更した後、後でもう一度テストしました。すべてのコアを許可すると、300 FPS を問題なく管理でき、シングル コア FPS との親和性は 4 に低下しました。シングル コアでマルチスレッド アプリを実行するのがそれほど悪いことではないことがわかりました。アフィニティを単一のコアに設定します。
これは、レンダリング/物理がどのように実行されるかについてです...
ループ開始
(1.0 / FPS) が経過するまで入力を収集します。
更新を呼び出します。
ゲーム内で物理データが使用されるため、物理スレッド ミューテックスをロックします。この更新呼び出しのすべてが完了するまで、エンジンは何も更新しないようにします。
Draw 関数オブジェクト (何を描画するか、どこに描画するか、どのように描画するかを保持する) を Render キューに送信するゲーム内のすべてを更新します。
ミューテックスのロックを解除します。
レンダラーは各関数オブジェクトで operator() を呼び出し、それらをキューから削除します。
画面を更新します。
ループを繰り返します。
物理スレッド ループ:
ALLEGRO_TIMER* timer(al_create_timer(1.0f / 60.0f));
double prevCount(0);
al_start_timer(timer);
while(true)
{
auto_mutex lock(m_mutex);
if(m_shutdown)
break;
if (!m_allowedToStep)
continue;
// Don't run too fast. This isn't final, just simple test code.
if (!(al_get_timer_count(timer) > prevCount))
continue;
prevCount = al_get_timer_count(timer);
m_world->Step(1.0f / 60.0f, 10, 10);
m_world->ClearForces();
}
// 注: 自動ミューテックスは、コンストラクタでミューテックスをロックし、デストラクタでロックを解除するために作成した単純なオブジェクトです。Allegro 5 のスレッド機能を使用しています。