将列表转换为numpy数组会产生比预期更大的内存

时间:2018-02-11 03:17:55

标签: python arrays numpy

我有一个包含2940个元素的列表 - 每个元素都是一个(60,2094)numpy数组。

print('DataX:')
print('len:')
print(len(dataX))
print('shape:')
for i in range(5):
    print(dataX[i].shape)
print('dtype:')
print(dataX[0].dtype)

print('size',sys.getsizeof(dataX)/1000000)

结果:

DataX:
len:
2940
shape:
(60, 2094)
(60, 2094)
(60, 2094)
(60, 2094)
(60, 2094)
dtype:
float64
size 0.023728

但是,如果我尝试将其转换为numpy数组(其形状应为(2940,60,2094)),则数组的大小会大得多。

#convert list to array

X = np.array(dataX)
print('X:')
print('shape', X.shape)
print('size',sys.getsizeof(X)/1000000)

输出:

DataX:
shape (2940, 60, 2094)
size 2955.052928

为什么会这样?

如果我尝试使用更大的数据集,我最终会遇到“内存”错误。

1 个答案:

答案 0 :(得分:1)

来自sys.getsizeof docs

  

只有直接归因于对象的内存消耗才是   占了,而不是它所指对象的内存消耗。

sys.getsizeof返回列表对象本身的内存消耗,不包括列表中包含的对象。您的一个阵列:

In [3]: arr = np.zeros(dtype=np.float64, shape=(60, 2094))

In [4]: arr.size
Out[4]: 125640

In [5]: arr.nbytes
Out[5]: 1005120 

包装基本数组的python对象增加了大约100个字节。

注意,作为对象的总是开销,请注意:

In [6]: sys.getsizeof(arr)
Out[6]: 1005232

实际内存消耗大约是:

In [7]: arr.nbytes*1e-9
Out[7]: 0.00100512 # one megabyte

如果我们有2940个,那么这些对象就是:

In [8]: arr.nbytes*2940*1e-9
Out[8]: 2.9550528000000003 # almost 3 gigabytes

如果我真的将这些全部放在一个列表中:

In [13]: alist = []

In [14]: alist.append(arr)

In [15]: for _ in range(2940 - 1):
    ...:     alist.append(arr.copy())
    ...:

list对象本身基本上由py_object指针数组支持。在我的机器(64位)上,指针将是一个机器字,即64位或8字节。所以:

In [19]: sys.getsizeof(alist)
Out[19]: 23728

In [20]: 8*len(alist) # 8 bytes per pointer
Out[20]: 23520

所以sys.getsizeof只考虑一个指针数组,加上对象开销,但是,即使关闭也不能解释数组对象消耗的3千兆字节数。指着。

瞧瞧:

In [21]: arr = np.array(alist)

In [22]: arr.shape
Out[22]: (2940, 60, 2094)

In [23]: arr.size
Out[23]: 369381600

In [24]: arr.nbytes
Out[24]: 2955052800

In [25]: arr.nbytes* 1e-9
Out[25]: 2.9550528000000003