Можно ли дать питону python первоначальную емкость (и это полезно)

Я заполняю python dict около 10 000 000 элементов. Мое понимание dict (или hashtables) заключается в том, что, когда в них возникает слишком много элементов, необходимо изменить размер, операцию, которая стоит довольно долгое время.

Есть ли способ сказать python dict, что вы будете хранить по крайней мере n элементов в нем, чтобы он мог выделить память с самого начала? Или эта оптимизация не принесет пользу моей скорости?

(И нет, я не проверял, что медленность моего маленького script из-за этого, я на самом деле не буду сейчас, как это сделать. Это, однако, что-то я сделал бы на Java, установил начальную емкость справа от HashSet)

Ответ 1

Во-первых, я слышал слухи о том, что вы можете установить размер словаря при инициализации, но я никогда не видел никакой документации или PEP, описывающих, как это будет сделано.

С учетом этого я провел анализ количества ваших предметов, описанных ниже. Хотя может потребоваться некоторое время для изменения размера словаря каждый раз, когда я рекомендую двигаться вперед, не беспокоясь об этом, по крайней мере, пока вы не сможете проверить его производительность.

Два правила, которые касаются нас при определении размера, - это количество элементов и коэффициент изменения размера. Словарь изменит размер, когда он будет заполнен на 2/3 при добавлении элемента, помещающего его поверх знака 2/3. Ниже 50 000 элементов он будет увеличиваться в 4 раза выше этой суммы в 2 раза. Используя вашу оценку в 10 000 000 элементов (между 2 ^ 23 и 2 ^ 24), ваш словарь будет изменять размер в 15 раз (в 7 раз ниже 50 тыс. 8 раз выше). Другой размер будет иметь место только за 11 100 000.

Изменение размера и замена текущих элементов в хеш-таблице занимает некоторое время, но мне интересно, заметите ли вы это с чем-то еще, что у вас есть в коде рядом. Я просто собрал набор времени, сравнивающий вставки в пяти местах вдоль каждой границы от размеров словаря от 2 ^ 3 до 2 ^ 24, а "пограничные" дополнения в среднем на 0,4 наносекунды дольше, чем "внеграничные" дополнения. Это на 0,17% больше... возможно, приемлемо. Минимальный для всех операций был 0,2085 микросекунды, а максимальный - 0,2412 микросекунды.

Надеюсь, что это проницательно, и если вы проверите производительность своего кода, проследите за редактированием! Мой основной ресурс для внутренних словарей был великолепным разговором, который дал Брэндон Роудс в PyCon 2010: The Mighty Dictionary

Ответ 2

Да, вы можете и вот решение, которое я нашел в вопросе другого человека, который также связан с вашим:

d = {}
for i in xrange(4000000):
d[i] = None
# 722ms

d = dict(itertools.izip(xrange(4000000), itertools.repeat(None)))
# 634ms

dict.fromkeys(xrange(4000000))
# 558ms

s = set(xrange(4000000))
dict.fromkeys(s)
# Not including set construction 353ms

Это разные способы инициализации словаря с определенным размером.