我知道在defaultdict中以我这种方式查询不存在的键会向defaultdict添加项。这就是为什么在性能方面可以将我的第二个代码片段与第一个进行比较。
import numpy as num
from collections import defaultdict
topKeys = range(16384)
keys = range(8192)
table = dict((k,defaultdict(int)) for k in topKeys)
dat = num.zeros((16384,8192), dtype="int32")
print "looping begins"
#how much memory should this use? I think it shouldn't use more that a few
#times the memory required to hold (16384*8192) int32's (512 mb), but
#it uses 11 GB!
for k in topKeys:
for j in keys:
dat[k,j] = table[k][j]
print "done"
这里发生了什么?此外,相比第一个脚本,这个类似的脚本需要运行数万年,并且使用的内存量也极高。
topKeys = range(16384)
keys = range(8192)
table = [(j,0) for k in topKeys for j in keys]
我猜测Python的整数可能是64位整数,这可能解释了其中一些问题,但是这些相对自然和简单的构造真的会产生如此巨大的开销吗? 我猜这些脚本表明确实会有这样的情况,所以我的问题是:到底是什么导致了第一个脚本的高内存使用率和第二个脚本的长运行时间和高内存使用率,并且有没有办法避免这些成本?
编辑: Python 2.6.4在64位机器上运行。
编辑2:我可以看出来,初步估计我的表应该占用3 GB 16384 * 8192 *(12 + 12)字节,而且如果使用defaultdict负载因子强制它保留双倍的空间,则需要6GB。 然后,内存分配的低效会再次增加2倍。
那么我的剩下的问题是: 有没有办法让它以某种方式使用32位整数?
为什么我的第二个代码片段与第一个相比要花费很长时间?第一个大约需要一分钟,而我在80分钟后终止了第二个。