2012-02-25 20 views
1

私はT[,,](3D配列)に似たデータ構造を探していますが、時間が経つにつれて外側に広がる(あえて妥当な上限を持たない)事前に寸法を知ることはできません。私は同様に負のインデックスを使用したいと思います。拡張可能な3D配列のデータ構造ですか?

唯一のことは、ある種類のPoint3構造体をキーにした辞書です。他の選択肢はありますか?私はできるだけ早く検索することを望みます。データは常に0,0,0の周りに集まります。どの方向にも拡張できますが、ポイント間には「ギャップ」はありません。


私は私が先に行くと、ちょうど今のDictionary<Point3, T>を使用し、それが実行する方法を確認するつもりだと思います。パフォーマンス上の問題がある場合は、負のインデックスを使用できるようにT[,,]のラッパーを作成してみます。

+0

N次元配列(実行時までの次元がわからない)を求めていますか?この配列で何をする予定ですか?あなたは配列があなたの問題の正しいデータ構造だと思いますか? –

+0

@ProgrammingHero:特に3次元。高速検索時間が重要なので、私は配列を考えていました。しかし、私はそれについてもっと考えていますが、最終的にデータをアンロードしなければならないと思うので(データが大きすぎます)、データの「中心」が0,0,0からシフトする可能性があります。それはゲームのためのもので、毎秒何千から何百万回呼ばれることがあります。 – mpen

+0

問題が発生した状況についてもう少し詳しく教えてください。また、サポートする必要のある非標準操作、つまり範囲クエリもありますか? –

答えて

1

配列が巨大になる可能性があるため、私はあなたにダイナミックアスペクトが必要であると想定しています。その場合、あなたが試みることができるのは、あなたのアレイを3dのタイルのセットとして割り当てることです。最上位レベルには、タイルへのポインタを格納する3次元データ構造があります。あなたはこれを展開して割り当てます。

それぞれの個々のタイルは、例えば、32x32x32のボクセルを含むことができる。またはあなたの目標に合った金額。 タイルを見上げるには、座標インデックスを32で割って(ビットシフトで)、タイルのインデックスは上位ビットをマスキングして計算されます。

このようなルックアップは、かなり安価で、.net辞書と同程度の可能性がありますが、メモリの使用量も少なくて済むため、パフォーマンスにも優れています。

しかし、結果として得られる配列はちょっと変わっていますが、配列の境界はタイルサイズの倍数です。

+0

これはまさに私が実際にやっていることです。私はタイルの塊をどうやって保管すべきか秘密に尋ねていた。 'タイル'自体は32x32x32の配列になります。つまり、どのデータ構造がポインタを保持していますか? – mpen

+0

まあ、私は偉大な心が似ていると思います。しかし、とにかく、何枚のタイルが必要ですか?何千?伝統的な配列を使用してタイルを格納し、必要に応じてより大きな配列にコピーすることができます。何百万ものタイルがあっても、より大きな配列にコピーするのはかなり速いはずです。私はあなたがフレームごとにこれを行う必要があるとは思わない... –

+0

私は100万近いタイルでレンダリングしているが、それは遅れている。私はより多くをサポートすることができます。私は従来の配列の周りにラッパーを構築しようとするかもしれないので、私は負のインデックスでアクセスすることができます...しかし、私はまずdictを試し、そのパフォーマンスがどのようになるか見てみましょう。 – mpen

2

データセットがどれだけ大きくなるかわからないため、明らかにこれを疎配列に似たデータ構造に格納する必要があります。だから、辞書は妥当と思われる。

私はここで少し狂っていますが、あなたの指数はSpherical Coordinatesにあるはずです。あなたのデータが外向きに成長するにつれ、私にとっては意味があります。また、(0、0、0)から特定の範囲の要素を見つけるのも非常に簡単です。

+0

以前は極座標を使っていましたが、それを3Dに拡張することは考えていませんでした。私のデータはあまりにもぎざぎざしているので、それはうまくいくとは思わない。すなわち、長さおよび角度が整数座標でうまく動作しない。 – mpen

+0

Hmmm、あなたは整数の角度と長さにそれらを変換することができます。あなたは球状ブロックを得るでしょう。私は変換があまりにも苦痛であるとは思わない - 確かにバランスの取れたKDツリーにノードを追加するO(logn)よりも少ない。 – zmbq

+0

さて、私の右にあるブロックが(1,0,0)で、「1」はベクトルの長さ、(0,0)は2つの角度です。それから私の目の前で斜めにブロックは何ですか?それはsqrt(2)の距離で、角度の1つで45度です。それをどのように整数で表しますか?私は浮動小数点を使用してそれを四捨五入することができましたが、いくつかのブロックが完全に見逃されていると思われます。 – mpen

2

範囲のクエリが必要な場合は、KD-Treesが考えられます。それらは木のような構造で、各レベルで1つの軸に沿って宇宙を2つに分けています。彼らはO(logN)ルックアップ時間(次元数が一定の場合)を提供しますが、それは十分速いかもしれないし、そうでないかもしれませんが、Sは検索された項目のサイズとても良い。彼らは動的データ(検索と一緒に挿入と削除)を扱うことができますが、結果として木がアンバランスになることがあります。また、あなたは、特定のポイントからNeighboor検索最寄行うことができます(つまり、10個の最寄りのオブジェクトが7,8,9)が(ポイントを得る)ウィキペディアは、いつものように、良い出発点である:膨大な数がある場合はhttp://en.wikipedia.org/wiki/Kd-tree

世界が非常にダイナミックであれば(物事は動いて、常に創造され/破壊される)、kd木は十分ではないかもしれません。ほとんどの場合、「あなたには(7,8,9)で物事を教えてください」と尋ねるだけで、あなたの質問で言及したようにハッシュを使うか、List<List<List<T>>>のようにすることができます。私はインターフェイス内で簡単に実装するだけで、パフォーマンスについては後で心配します。

+0

私はKDツリーが遅すぎると思っています。それは簡単なので、私は最初に推測する辞書から始めます。 – mpen

1

アレイアクセスは非常に高速なリニアルックアップです。検索の速度が優先される場合は、配列の変更頻度に応じて移動することをお勧めします。

チャンクをプレーヤの周りに維持することを目標とする場合、プレーヤの周囲に「現在の世界」の配列構造を配置して、中央のチャンクが9,9,9の3次元配列[20,20,20]です。プレイヤーが中央のチャンクを別のチャンクに移動するたびに、古いチャンクをドロップして移動するように配列のインデックスを再作成します。

最終的には、ゲームエンジンを最適化する方法についてのオプションを求めていますが、どちらが正しいかを言うのはほとんど不可能です。ゲームは他のアプリケーションよりもパフォーマンスがより最適化される傾向がありますが、マイクロ最適化に惹かれないようにしてください。最初にの可読性をに最適化してから、必要なときにパフォーマンスを最適化してください。

この特定のデータ構造がエンジンのボトルネックになると思われる場合は、いくつかのパフォーマンスのトレースを入れて、エンジンを稼働させたらどちらか一方を確かめるのは簡単です。

+0

私は早すぎる最適化の悩みを知っていますが、すでに何かが走っています。私はすでにmaxを打っていますし、ほとんど機能を実装していません。配列のインデックスを再作成すると、コストがかかります。センターが透過的に移動できるように 'T [,,]'の周りにラッパーを作る方が良いのではないでしょうか?つまり、 '0,0,0'は' T [0,0,0] 'にマッピングされないかもしれません。それから私ははるかに大きな配列、例えば100x100x100を割り当て、50,50,50周りに中心を置き、おそらく10x10x10を使い切ることができますが、それがエッジからシフトするまで再インデックスする必要はありません... – mpen

+1

これが理由ですあなたが作る情報だけを持っているのです。センターが変更されるたびにインデックスを再作成すると、このイベントが発生するたびに8000個の参照を更新する必要があります。抽象化を行う場合は、マトリックスでルックアップを行うたびに座標変換を適用する必要があります。あなたのエンジンだけでなく、あなたのエンジンも知らなくても、どちらが速くなるのかは分かりません。それでも、両方のオプションをベンチマークしたいと思っています。 –

+0

追加する価値があります:あなたの問題は、あなたが多くの直接参照をしている可能性があります。あなたはその数を減らす方法を考えましたか? –

関連する問題