3

私は最近、ゲームを作成するプロジェクトから始めました(私はちょっと新しいです)。そして、パフォーマンスを向上させるためにマルチスレッドを実装する方法について考え始めました。

ゲームにユニットがあり、そのユニットに位置xとが含まれているとしyます。この位置は、インターネットから1つのトレッドによって更新され、別のスレッドがx,yユニットのグラフィックをレンダリングするために使用しています(どこにあるかを知る必要があります)。

ここで、これらの変数にミューテックスまたはセファモア(どちらを使用するのが最適かは少しわかりません)を設定するとします。もちろん、問題はレンダリングスレッドにあります。立ち止まって待つことはできません。ゲームが遅くなります。ただし、これはインターネットスレッドでは問題になりません。何か問題がない限り、ゲームを更新するのにさらに数ミリ秒は関係ありません。

そこで、どうすればこの問題を解決できるかを考えていたところ、アイデアが浮かびました。2セットを作成するとx,yします(これからはx、単純にするためにのみ使用できますが、アイデアは得られます)。だからあなたはとを持っていx1ますx2

  • 現在、インターネットスレッドはx1のみを更新しました。
  • グラフィックスレッドはx1を使用してから、x2を現在の値に更新します。

今ここにアイデア。がインターネットスレッドからロックされている場合x1、グラフィックスレッドは次のように表示します

「ねえ、私は待つことができません。それx2は位置の非常に良い近似であるため、私は先に進んで使用します。」

x1そして、それは再び自由になるまでそうします。こんな感じになります。

//Thread Graphics:
if (x1 is not locked){
    lock x1:
        use x1
    unlock x1:
    x2=x1
}else{
    use x2
}

//Thread Internet:

wait until x1 is unlocked:
lock x1:
    save data to x1
unlock x1:

これは余分なメモリを消費することに気づきましたが、少なくともこの手法の使用を重要なデータのみに制限する場合は、それだけの価値があると思います。

だから私の質問は:皆さんはこのアイデアについてどう思いますか?多分それはすでに一般的なテクニックです、私だけがそれの名前を知りません。このような問題を解決する方法について他にフィードバックがあれば、よろしくお願いします。これはほとんどのプログラマーに共通の問題だと思います。

4

5 に答える 5

0

これは、スレッド セーフを維持する優れた方法であり、ダブル バッファリングについて考える場合は拡張できます。私が取り組んできたプロジェクトでは、同様の原則で機能するスレッドセーフなデータベースがありました。

  • データには、書き込みバッファーと読み取りバッファーの 2 つのコピーがあります。
  • データベースが書き込まれるたびに、書き込みバッファが使用されます。
  • それが読み取られるとき、それは読み取りバッファを使用します。
  • 各フレームの終わりにバッファーが交換されるため、読み取りバッファーは書き込みバッファーになり、その逆も同様です。

レンダリング スレッドでのダブル バッファリングとの類似点を確認できるはずです。これにより、プロジェクト全体でスレッド セーフを維持することができました。もちろん、トレードオフは、データベース内のすべてのメモリ使用量を 2 倍にすることであり、大量のデータを保存するには理想的ではありません。私たちの最大のヒットは通常、単一のスレッドでのみ使用されるレンダリング データと AI データであったため、これは大きな問題ではありませんでした。

編集: 2 番目のトレードオフについて言及するのを忘れていました: データベースの値を変更すると、次のフレームまで有効になりません。これは私たちにとって大きな問題ではありませんでした。システムを作成するときに、このことを念頭に置く必要がありました。

于 2013-02-21T03:45:30.100 に答える
0

余分なメモリを使用することは悪い考えではありません。

データの処理中に x1 をロックしたままにしないと、アルゴリズムを改善できます。

これの代わりに

//Thread Graphics:
if (x1 is not locked){
    lock x1:
        use x1
    unlock x1:
    x2=x1
}else{
    use x2
}

このようなものを使用してください

//Thread Graphics:
if (x1 is not locked)
    lock x1:
        x2=x1
    unlock x1:

use x2
于 2013-02-20T12:56:07.093 に答える
0

このアイデアは気に入っていますが、ゲーム内のアクションを予測することの影響について懸念しています。ミューテックスで保護された(共有)データができるだけ小さなセクションで保護されていることを確認することに集中した方がよいように思えます。たとえば、描画中にオブジェクト全体をロックする代わりに、ロックを実行し、必要なものをコピーしてから、ロックを解除してから描画します。インターネット側でも同じこと...更新を待ち、取得し、ロックし、更新し、ロックを解除します。

于 2013-02-20T12:36:59.837 に答える
0

私のゲームでは、各フレームの最後に関数のリストを実行します。

スレッド 1: 位置を取得するためにサーバーを呼び出します

スレッド 2: X、Y でオブジェクトのフレームをレンダリングします。

スレッド 2: スレッド 1 からの作業をチェックします。

スレッド 2: 作業はありません。続行します。

スレッド 1: X、Y を受け取ります。

スレッド 1: 最終的な X、Y を設定する作業オブジェクトを作成します

スレッド 1: スレッド 2 の作業キューをロックします。

スレッド 1: 作業オブジェクトを作業キューにプッシュします

スレッド 1: スレッド 2 作業キューのロックを解除します。

スレッド 2: X、Y でオブジェクトのフレームをレンダリングします。

スレッド 2: スレッド 1 からの作業をチェックします。

スレッド 2: FOUND WORK! ワーク キューをロックしています...

スレッド 2: スレッド 1 の作業を使用してオブジェクト X、Y を設定します。

スレッド 2: 作業オブジェクトを削除します

スレッド 2: ワーク キューのロックを解除する

スレッド 2: レンダリング ループを続行します

または、フレームのレンダリングが終了するまで待って、しばらく一時停止し、値を更新してから、レンダリング スレッドの一時停止を解除することもできます。

于 2013-02-20T12:39:38.993 に答える
0

実際、データの複製は、ある時点 (遠い未来) で試してみようと思っていたものとほぼ同じです。C++ でも非常に簡単に実行できるアイデアです。

値の基本型 (DualInt、DualFloat など) を実装し、すべての標準演算子を提供すると、データを 2 要素配列に内部的に格納できます。ゲッターは要素 0 を取得し、セッターは要素 1 を変更します。

トリックは、それらを切り替えることです。必要なのは、getter と setter がリーダー部分を使用し、switcher がライター部分を使用するリーダー/ライター ロックを設定することだけです。切り替える必要があるまで、複数のリーダーを読み取らせることができます (実際には、古くなって新しい値を設定します)。次に、ロックのライター部分を取得し (新しいリーダーを防ぎ、すべてのリーダーが終了するまで待機します)、どの要素から読み取られ、どの要素に書き込まれるかを示すグローバル変数を切り替えます。

大騒ぎも面倒も、多くの値をコピーする必要もありません。

于 2013-02-20T13:42:56.327 に答える