В настоящее время (numba 0.46.0) то, что вы намеревались сделать, скорее всего, невозможно с DictType
.
sys.getsizeof
для контейнеров в лучшем случае сложно и вводит в заблуждение в худшем случае. Проблема заключается в том, что getsizeof
необходимо сократить возможно очень сложные детали реализации до одного целого числа.
Первая проблема заключается в том, что вызов sys.getsizeof
для контейнера обычно сообщает только о размере контейнера, а не о содержимом контейнер - или в случае непрозрачного контейнера он возвращает только размер оболочки. Вы столкнулись с последним: DictType
- это просто оболочка для непрозрачной структуры numba, которая определена (вероятно) в c. Таким образом, 64
, который вы видите, на самом деле правильный, это размер оболочки. Возможно, вы можете получить доступ к упакованному типу, но, учитывая, что он скрыт за закрытыми атрибутами, он не предназначен для не-numba-кода, поэтому я не буду go идти по этому пути - в основном потому, что любой ответ, основанный на таких деталях реализации, может быть устаревшим в любое время.
Однако sys.getsizeof
требует глубокого понимания деталей реализации для правильной интерпретации. Так что даже для простого dict
не очевидно, что представляет число. Это, конечно, вычисленная память в байтах контейнера (без содержимого), но это также может быть словарь совместного использования ключей (в вашем случае это не словарь совместного использования ключей), где число будет точным, но так как часть ключа совместное использование словаря - это не тот номер, который вы ищете. Как уже упоминалось, обычно он также не учитывает содержимое контейнера, но это также деталь реализации, например, numpy.array
включает размер содержимого, тогда как list
, set
, et c. нет. Это связано с тем, что массив numpy не имеет «реального содержимого» - по крайней мере он не содержит Python объектов в качестве содержимого.
Так что даже если оболочка DictType
сообщит о размере базовый словарь, вам все равно нужно знать, содержит ли он содержимое в словаре, или как указатель на Python объекты или (даже более запутанный) как объекты, определенные в другом языке (например, C или C ++) для интерпретации результаты правильные.
Поэтому я бы посоветовал вам , а не , использовать sys.getsizeof
, кроме как из любопытства или интереса c. И только тогда, если вы готовы копаться во всех деталях реализации (которые могут меняться или не меняться в любое время), чтобы правильно интерпретировать результаты. Если вы действительно заинтересованы в потреблении памяти, вам часто лучше использовать инструмент, который отслеживает использование памяти вашей программой в целом. Это все еще имеет много подводных камней (повторное использование памяти, неиспользуемые выделения памяти) и требует значительного объема знаний о том, как память используется для правильной интерпретации (виртуальная память, разделяемая память и как выделяется память), но часто дает более realisti c посмотреть, сколько памяти фактически использует ваша программа.
import gc
import numba as nb
import psutil
@nb.njit
def get_dict(n):
d = {0:0}
for i in range(1,n):
d[i] = i
return d
get_dict(1)
gc.collect()
print(psutil.Process().memory_info())
d = get_dict(100_000)
gc.collect()
print(psutil.Process().memory_info())
Что дает на моем компьютере:
pmem(rss=120696832, vms=100913152, num_page_faults=34254, peak_wset=120700928,
wset=120696832, peak_paged_pool=724280, paged_pool=724280, peak_nonpaged_pool=1255376,
nonpaged_pool=110224, pagefile=100913152, peak_pagefile=100913152, private=100913152)
pmem(rss=126820352, vms=107073536, num_page_faults=36717, peak_wset=129449984,
wset=126820352, peak_paged_pool=724280, paged_pool=724280, peak_nonpaged_pool=1255376,
nonpaged_pool=110216, pagefile=107073536, peak_pagefile=109703168, private=107073536)
Что показывает, что программе требовалось 6 123 520
байт памяти ( использование "rss" - размер резидентного набора) больше после вызова, чем было выделено ранее.
И аналогично для простого Python словаря:
import gc
import psutil
gc.collect()
print(psutil.Process().memory_info())
d = {i: i for i in range(100_000)}
gc.collect()
print(psutil.Process().memory_info())
del d
gc.collect()
Что дало разницу в 8 552 448
байтов на моем компьютере.
Обратите внимание, что эти числа представляют собой полный процесс, поэтому относитесь к ним с осторожностью. Например, для небольших значений (get_dict(10)
) они возвращают 4096
на моем windows компьютере, потому что это размер страницы windows. Программа фактически выделяет больше места, чем нужно словарю из-за ограничений ОС.
Однако даже с учетом этих ловушек и ограничений это все же значительно точнее, если вас интересуют требования к памяти для вашей программы.
Если вы все еще (из любопытства) хотите узнать, сколько памяти теоретически нужно DictType
, вам, вероятно, следует попросить разработчиков numba улучшить numba, чтобы они внедрили __sizeof__
для своих оболочек Python, чтобы числа являются более представительными. Вы можете, например, открыть проблему на их трекере или задать в их списке рассылки .
Альтернативой может быть использование других сторонних инструментов, например pypmler
, но я сам ими не пользовался, поэтому не знаю, работают ли они в этом случае.