3

私は天の川の単純なモデルを構築しています。保存する必要があるものの 1 つは、質量密度の 3D グリッドです。

問題は、銀河の周りに長方形のボックスを配置すると、ほとんどのグリッド セルが空になることです。これにより、役に立たないゼロをたくさん節約できます。したがって、単純な配列は無駄に思えます。

galaxy = [[[0 for k in xrange(1601)] for j in xrange(1601)] for i in xrange(253)]
# then fill in i,j,k values that are non-zero

辞書を使用してスパース配列を構築しようとしました:

for x in range(1601):
    for y in range(1601):
        for z in range (253):
            galaxy[str(x) + "," + str(y) + "," + str(z)] = # whatever

しかし、(醜いことは別として)キーに使用していた文字列は、保存していたよりも多くのメモリを占有していました。OutOfMemoryError(私が計算した) キーだけで数ギガのメモリを消費していたので、私は sを得ました。

ある時点で、モデルの解像度を上げたいと思うでしょう。それは、より大きなグリッドを意味します。float の 3D 配列を使用するよりも効率的に値を格納する方法はありますか?

また、すべてのセル (またはグリッド内のゼロ以外のセルのみ) を反復処理するのにかかる時間についても懸念しています。これは非常に重要です。

4

3 に答える 3

2

簡単な計算:1601 * 1601 * 253 => 648489853 items。テストによると、ディクショナリは32ビットマシンではエントリごとに約24バイト、64ビットマシンでは49バイト、つまり15,563,756,472バイト(64ビットでは30GB)になります。その10%は1.5GB(または64ビットでは3.0GB)です。大量のメモリを備えた64ビットシステムを使用している場合は、スパース表現で問題ないと思います。

私はお勧め:

  1. 文字列ではなくタプルをキーとして使用し、
  2. ゼロ値を格納しないスパースストレージシステムを使用します。

これが1つの可能性です:

class SparseDict(dict):
  def __init__(self, default_value):
    dict.__init__(self)
    self._value = default_value
  def __getitem__(self, key):
    try:
      return dict.__getitem__(self, key)
    except KeyError:
      return self._value
  def __setitem__(self, key, val):
    # I'm sure this can go faster if I were smarter
    if val == self._value:
      if  key in self:
        del self[key]
    else:
      dict.__setitem__(self, key, val)

def test(galaxy):
  import sys
  print len(galaxy), sys.getsizeof(galaxy)

  # test is 1/10th size in each dimension,
  # so 1/1000th of the volume
  for x in range(160):
    for y in range(160):
      for z in range (25):
        import random
        # 90% of space is essentially a vacuum
        if random.random() < .1:
          galaxy[x,y,z] = 1502100
        else:
          galaxy[x,y,z] = 0

  print len(galaxy), sys.getsizeof(galaxy)

test(SparseDict(0))
于 2013-02-28T21:16:40.860 に答える
2

ディクショナリ アプローチを使用してみてください。ただし、値がゼロ以外のキーのキーと値のペアのみを保存してください。より良いキーは (x,y,z) のタプルかもしれません。

于 2013-02-28T20:27:29.543 に答える
0

たぶん、SQLテーブルにデータを保存し、必要に応じてキューブのサブセットのみをロードしてみてください。これにより、パーツのロードに時間がかかりますが、メモリを節約できます。メモリ内の表現については、辞書などの他の回答で提案されている方法を使用してください。

于 2013-02-28T20:36:36.403 に答える