21

これは「難しい」質問です。Web 上で興味深いものは何も見つかりませんでした。

会社でメモリ管理モジュールを開発しています。次世代コンソール (Xbox 360、PS3、PC... PC をコンソールと見なしています) 向けのゲームを開発しています。

将来、次のゲームでは、メイン コンソール メモリにすべてをロードすることができない大規模なゲーム ワールドのテクスチャ ストリーミングを処理する必要があります (今のところ PC については話していません)。

最初に、テクスチャの高解像度ミップマップ (ワールド データのサイズの約 70%) をストリーミングします。将来的には、ジオメトリ、小さなミップマップ、オーディオなどもストリーミングする必要があるかもしれません.

X360に焦点を当てた、その問題のためのメモリマネージャーを開発しています(PS3を介してホストメモリと関連する自動最適化GMMアロケーターを使用できるため)。

私が直面している問題は次のとおりです。テクスチャ ストリーミング用に特定のメモリ領域 (たとえば 64 メガバイト) を予約することに決め、その領域内のすべての割り当てと割り当て解除を処理したいと考えています。アプリケーションの開始時に領域を割り当てており、その領域は物理的に連続していることが保証されています (仮想だけでなく、そこにテクスチャを格納する必要があるため)。

ポインターの代わりにハンドルを使用して、自動最適化アロケーターを実装しました。時間は問題ではありません。問題はメモリの断片化です。ゲームでは、ストリーミング ターゲットを継続的にロードおよびアンロードするため、バッファーの最大量 (64 メガバイト) を使用したいと考えています。

このアロケーターを使用すると、割り当てられたスペースをすべて使用できますが、最適化ルーチンは許容できない時間 (フレームよりも長い 60 ミリ秒) で動作しますが、アルゴリズムはそれほど悪くはありません... 避けられない memcpy が多すぎます!

この問題を解決するソリューションを探しています。少なくとも良い論文、または事後分析、または私と同じ問題に直面した人を見つけたいと思います.

今、私は 2 つの戦略から選択しています: 1) 最適化ルーチンを専用スレッドに移動します (6 つの hw スレッドを使用する X360 には適していますが、ハードウェア スレッドのみを使用する PS3 には適していません... SPU を使用するように言わないでください!)領域のロック、移動中の領域へのアクセスなど、すべてのマルチスレッドの問題について...メモリ マネージャーは、フレームごとに予算内で実行できることを実行します。

誰かが彼の経験を教えてもらえますか?

4

5 に答える 5

13

私は最近、メモリ管理に関して多くの調査を行いましたが、これはネット上で見つけた最も有益で役立つ記事です。

http://www.ibm.com/developerworks/linux/library/l-memory/

その論文に基づいて、得られる最良かつ最速の結果は、64 MB を同じサイズのチャンクに分割することです。チャンクのサイズは、オブジェクトのサイズによって異なります。一度に完全なチャンクを割り当てたり、割り当てを解除したりします。これは

  1. インクリメンタル ガベージ コレクションよりも高速です。
  2. よりシンプル。
  3. そして、その「断片化が多すぎる」問題をある程度解決します。

それを読むと、考えられるすべての解決策と、それぞれの長所と短所に関する優れた情報が見つかります。

于 2009-03-19T12:14:12.227 に答える
5

ストリーミング テクスチャとテクスチャ サイズごとのプールに複数のメモリ領域を使用しないのはなぜですか?

Insomniac には、PS3 でのテクスチャ ストリーミングの実装に関する論文があります。参考になると思います: link

断片化を最小限に抑えるための一般的な割り当て戦略については、Doug Leaが役立つかもしれません。

しかし、あなたの質問を読んだところ、考えすぎているように思えます。プールされたアプローチを強くお勧めします。(また、書き込み結合メモリで最適化パスを実行することは、特に安全でも楽しいとも思えません。)

于 2009-03-20T19:47:02.230 に答える
2

ハンドルを使用しているため、メモリを自由に移動できます。別のスレッドを使用することは、おそらく最善の (最も安全または最速の) 方法ではないと思います。私の推測では、圧縮 (メモリ内で前方または後方にコピー) する、一種のインクリメンタル コピー アロケータを使用する方がmalloc()よいでしょう。 free()) いくつかの割り当てられたブロック。コピーしたバイト数によって、定期的に初期値にリセットされる「予算」が使い果たされます (たとえば、画面が更新されるたびに)。(もちろん、ブロック全体のみがコピーされます。)

特定のバイト数をコピーするにはかなり予測可能な時間がかかるため、画面の更新ごとに安全に実行できるコピーのバイト数を推定し、それに制限することができます。予算内に十分な時間があれば、malloc()orを呼び出すとfree()メモリが完全に最適化されます。

ここで未解決のままにしておく質問がいくつかあります。たとえば、メモリを正確に圧縮する方法などです。標準の非インクリメンタル コピー アロケーターは、前面から割り当てを開始し、メモリが不足したときにすべてを背面にコピー (前面のメモリを解放) できますが、ここではその自由はありません。ブロックを前方または後方に移動するかどうかを決定するには、いくつかのヒューリスティックが必要になる場合があります。malloc()重要なことは振動を避けることです (またはを連続して呼び出すと、同じブロックが前方に移動してから後方に移動しますfree())。

于 2009-03-19T17:02:01.340 に答える
2

メモリ管理を避けるために、固定サイズのスロット (256x256、512x512、1024x1024、および 2048x2048 テクスチャ) をそれぞれ 2 つの形式 (DXT1 および DXT5) で割り当てることを除いて、あなたが説明したシステムとほとんど同じです。

于 2009-07-12T14:13:09.710 に答える
1

漸進的なアプローチをお勧めします。各フレームは、両側に空き領域がある inuse メモリの連続ブロックを見つけ、それが収まる方向に移動します。または、すべてのブロックを一方向に移動し、ギャップとそれに最適な使用中のブロックを見つけて移動することもできます。360 ではおそらくスレッドを使用して移動する必要がありますが、PS3 では GPU を使用してデータを移動するのが最適です。

于 2009-03-20T19:28:20.217 に答える