我试图了解Python对象使用了多少内存。
在以下代码中,我检查了numpy数组vs列表以及带下标的numpy数组的内存:
import sys, os, psutil, numpy as np
def size_of(obj):
return f'{sys.getsizeof(obj) / 1000000:,.0f} MB'
def get_memory_usage():
process = psutil.Process(os.getpid())
return f'{process.memory_info().rss / 1000000:,.0f} MB'
# Numpy vs List
print(f'(1) Mem usage: {get_memory_usage()}')
ONE_HUNDRED_MIL_NP = np.random.randint(-128,127,int(10**8),dtype='int8')
print(f'(2) Mem usage: {get_memory_usage()}, ONE_HUNDRED_MIL_NP: {size_of(ONE_HUNDRED_MIL_NP)}')
ONE_HUNDRED_MIL_LIST = list(np.random.choice(127, int(10**8), replace=True).astype('int8'))
print(f'(3) Mem usage: {get_memory_usage()}, ONE_HUNDRED_MIL_LIST: {size_of(ONE_HUNDRED_MIL_LIST)}')
# Now try subscriping
FOURCOLS = np.random.randint(-128,127,size=(int(10**8),4),dtype='int8')
print(f'(4) Mem usage: {get_memory_usage()}, FOURCOLS: {size_of(FOURCOLS)}')
FOURCOLS_PERMUTED = FOURCOLS[np.random.randint(0,len(FOURCOLS),size=len(FOURCOLS),dtype='int32')]
print(f'(5) Mem usage: {get_memory_usage()}, FOURCOLS_PERMUTED: {size_of(FOURCOLS_PERMUTED)}')
这将返回:
(1) Mem usage: 187 MB
(2) Mem usage: 287 MB, ONE_HUNDRED_MIL_NP: 100 MB
(3) Mem usage: 3,526 MB, ONE_HUNDRED_MIL_LIST: 900 MB
(4) Mem usage: 3,926 MB, FOURCOLS: 400 MB
(5) Mem usage: 4,326 MB, FOURCOLS_PERMUTED: 400 MB
注意:
谢谢
答案 0 :(得分:0)
ONE_HUNDRED_MIL_NP = np.random.randint(-128,127,int(10**8),dtype='int8')
这将创建一个数组。 ONE_HUNDRED_MIL_NP.nbytes
是衡量数组大小的好方法。数组具有一些基本信息,例如形状,步幅,dtype,但大部分空间是一个包含字节的1d数据缓冲区,在这种情况下,每个元素为字节。
ONE_HUNDRED_MIL_LIST = list(np.random.choice(127, int(10**8), replace=True).astype('int8'))
这将从该数组生成一个列表。列表具有一个数据缓冲区,其中包含对内存中其他对象的引用。 getsizeof
仅测量该缓冲区的大小,而对对象什么也没说。这些对象是numpy.int8
对象,它们是从数组中提取的。它们实际上并不引用数组的元素,而是这些值的副本。
从数组中获取列表的更好方法是使用arr.tolist()
。
FOURCOLS = np.random.randint(-128,127,size=(int(10**8),4),dtype='int8')
这只是另一个数组。 2d形状不会改变占用的内存量。
FOURCOLS_PERMUTED = FOURCOLS[np.random.randint(0,len(FOURCOLS),size=len(FOURCOLS),dtype='int32')]
这是advanced indexing
的示例。它使用自己的数据缓冲区(而不是带有共享缓冲区的view
)创建一个新数组。是的,您只是索引第一维,但是数据缓冲区存储所有值,而不是对FOURCOLS行的引用。
列表列表确实存储对嵌套列表的引用或指向。因此,对外部列表进行混排只会对引用进行混排。多维c
数组还存储引用或指针。但是多维numpy数组使用不同的模型。数据是平面c
数组。多维性是由shape/strides
迭代代码产生的。
因此,请查看您的电话号码:
(1) Mem usage: 187 MB
基本用法。
(2) Mem usage: 287 MB, ONE_HUNDRED_MIL_NP: 100 MB
为基础增加100mb。
(3) Mem usage: 3,526 MB, ONE_HUNDRED_MIL_LIST: 900 MB
900大约是列表的数据缓冲区使用的内存。总使用量增加的其余部分是用于存储10 ** 8 np.int8
个对象。
(4) Mem usage: 3,926 MB, FOURCOLS: 400 MB
这将显示另外400 MB的内存使用情况。
(5) Mem usage: 4,326 MB, FOURCOLS_PERMUTED: 400 MB
还有另外400个。
在没有(3)列表的情况下,创建mem usage
应该显示出数组大小的有序增加。