我正在构建一个银河系的简单模型,我需要存储的一个东西是质量密度的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
因为(我计算过)单独的密钥需要几个记忆。
在某些时候,我会想要提高我的模型的分辨率,这将意味着更大的网格。 存储我的值的方法是否比使用3D数组浮点数更有效?
我还担心迭代所有单元格(或者只是网格中的非零单元格所需的时间。这将非常重要。
答案 0 :(得分:2)
尝试使用字典方法,但只存储值为非零的键的值:值对。更好的密钥可能是(x,y,z)的元组。
答案 1 :(得分:2)
快速数学:1601 * 1601 * 253 => 648489853 items
。测试表明字典在32位机器上每个条目大约需要24个字节,在64位机器上需要49个字节,所以这是
15,563,756,472字节(或64位时30GB)。其中10%是1.5GB(或64位时为3.0GB)。如果你有一个带有大量内存的64位系统,我认为你可以使用稀疏表示。
我建议:
这是一种可能性:
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))
答案 2 :(得分:0)
也许尝试将数据保存在sql表中,并根据需要仅加载多维数据集的子集。这将花费你及时加载零件,但会节省你的记忆。至于内存重新定位,请使用其他答案中建议的方法,如字典等......