Я понимаю, что запрос несуществующего ключа в 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 (512 mb), but
#it uses 11 GB!
for k in topKeys:
for j in keys:
dat[k,j] = table[k][j]
print "done"
Что здесь происходит? Кроме того, этот аналогичный script занимает эоны для запуска по сравнению с первым, а также использует абсурдное количество памяти.
topKeys = range(16384)
keys = range(8192)
table = [(j,0) for k in topKeys for j in keys]
Я предполагаю, что для python ints могут быть 64-битные ints, что будет объяснять некоторые из них, но действительно ли эти относительно естественные и простые конструкции действительно создают такие большие накладные расходы? Я предполагаю, что эти сценарии показывают, что они это делают, поэтому мой вопрос: что именно вызывает использование высокой памяти в первом script и длительной продолжительности работы и использовании большой памяти второго script, и есть ли способ избежать этих расходы?
Изменить: Python 2.6.4 на 64-разрядной машине.
Изменить 2: я понимаю, почему в первом приближении моя таблица должна занимать 3 ГБ 16384 * 8192 * (12 + 12) байт и 6 ГБ с коэффициентом нагрузки по умолчанию, который заставляет его резервировать удвоенное пространство. Тогда неэффективность в распределении памяти съедает еще один фактор в 2 раза.
Итак, вот мои оставшиеся вопросы: Есть ли способ, чтобы я сказал, чтобы использовать 32-битные ints?
И почему мой второй фрагмент кода принимает FOREVER для запуска по сравнению с первым? Первый занимает около минуты, и я убил второй после 80 минут.