我试图获得Numba类型字典的大小(以字节为单位):
from numba import njit
from numba.typed import Dict
from sys import getsizeof as gso
@njit
def get_dict(n):
d = {0:0}
for i in range(1,n):
d[i] = i
return d
print(gso(get_dict(10))
print(gso(get_dict(10000)))在这两种情况下,getsizeof函数都返回64字节。显然,字典的大小必须取决于长度。
如果我使用dict()将类型化字典转换为本机Python字典,则它工作并返回376和295016:
print(gso(dict(get_dict(10))))
print(gso(dict(get_dict(10000))))我怎么测量它呢?
发布于 2020-01-08 11:37:36
目前(Numba0.46.0),您想要做的事情很可能不可能在DictType中实现。
sys.getsizeof on containers充其量是棘手的,在最坏的情况下非常具有误导性。问题是,getsizeof需要将可能非常复杂的实现细节简化为一个整数。
第一个问题是,调用容器上的sys.getsizeof通常只报告容器的大小,而不是容器的内容--如果是不透明的容器,则只返回包装器的大小。您所遇到的是后者-- DictType只是一个在C中定义(可能)的不透明numba结构的包装器。所以您看到的64实际上是正确的,这就是包装器的大小。您可能可以访问包装的类型,但是考虑到它隐藏在私有属性后面,所以它不是针对非numba代码的,所以我不会继续这样做--主要是因为依赖于这些实现细节的任何答案在任何时候都可能过时。
但是,sys.getsizeof需要对实现细节有深入的理解才能正确解释。因此,即使对于普通的dict,数字代表什么也不明显。当然,它是以字节为单位计算的容器内存(没有内容),但它也可能是密钥共享字典(在您的例子中,它不是密钥共享字典),其中的数字将是准确的,但是由于密钥共享字典的一部分是共享的,所以它可能不是您要查找的数字。如前所述,它通常也不考虑容器的内容,但这也是实现细节,例如,numpy.array包含内容的大小,而list、set等则不包括。这是因为numpy数组没有“真正的内容”--至少它没有将Python作为内容。
因此,即使DictType包装器会报告底层字典的大小,您仍然需要知道它是否包含字典中的内容,或者作为指向Python的指针,或者(更复杂的)作为用另一种语言(如C或C++)定义的对象来正确解释结果。
因此,我的建议是,不要使用sys.getsizeof,除非出于好奇或学术兴趣。然后,只有当您愿意深入研究所有的实现细节(可能更改或不更改任何时间),才能正确解释结果。如果您真的对内存消耗感兴趣,您通常最好使用一个工具来跟踪整个程序的内存使用情况。这仍然有很多缺陷(内存重用、未使用的内存分配),并且需要大量的知识--如何使用内存来正确解释(虚拟内存、共享内存,以及如何分配内存),但它通常会产生一个更真实的视图,即您的程序实际使用了多少内存。
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)),它们在我的windows计算机上返回4096,因为这是窗口的页面大小。由于操作系统的限制,那里的程序实际上分配了比字典需要的更多的空间。
然而,即使存在这些缺陷和限制,如果您对程序的内存需求感兴趣,这仍然是非常准确的。
如果您仍然(出于好奇)想知道DictType理论上需要多少内存,那么您可能应该要求numba开发人员增强numba,以便他们为他们的Python实现__sizeof__,从而使数字更具代表性。例如,可以使用在他们的问题追踪器上打开一个问题或在他们的邮件列表上询问。
另一种选择可能是使用其他第三方工具,例如pypmler,但是我自己还没有使用这些工具,所以我不知道它们在这种情况下是否有效。
https://stackoverflow.com/questions/59642027
复制相似问题