numpy数组的Python内存使用情况


156

我正在使用python分析一些大文件,并且遇到了内存问题,因此我一直在使用sys.getsizeof()来跟踪使用情况,但是numpy数组的行为很奇怪。这是一个涉及我必须打开的反照率地图的示例:

>>> import numpy as np
>>> import struct
>>> from sys import getsizeof
>>> f = open('Albedo_map.assoc', 'rb')
>>> getsizeof(f)
144
>>> albedo = struct.unpack('%df' % (7200*3600), f.read(7200*3600*4))
>>> getsizeof(albedo)
207360056
>>> albedo = np.array(albedo).reshape(3600,7200)
>>> getsizeof(albedo)
80

数据仍然存在,但是对象的大小(3600x7200像素图)已从约200 Mb变为80字节。我希望我的内存问题已经解决,并将所有内容都转换为numpy数组,但是我认为这种行为(如果为真)在某种程度上会违反某些信息论定律或热力学定律,等等。倾向于相信getsizeof()不适用于numpy数组。有任何想法吗?


8
从文档开始sys.getsizeof:“返回对象的大小(以字节为单位。该对象可以是任何类型的对象。所有内置对象都将返回正确的结果,但是对于第三方扩展而言,这不必成立)具体实现方式。仅考虑直接归因于该对象的内存消耗,而不考虑它所引用的对象的内存消耗。”
乔尔·科内特

1
getsizeof不能可靠地指示内存消耗,尤其是对于第三方扩展而言。
乔尔·科内特

13
基本上,这里的问题resize是返回一个view,而不是一个新的数组。您正在获取视图的大小,而不是实际数据。
mgilson 2012年

为此,sys.getsizeof(albedo.base)将给出非视图的大小。
埃里克

Answers:


236

您可以将其array.nbytes用于numpy数组,例如:

>>> import numpy as np
>>> from sys import getsizeof
>>> a = [0] * 1024
>>> b = np.array(a)
>>> getsizeof(a)
8264
>>> b.nbytes
8192

执行导入sys后,其sys.getsizeof(a)。
涡流

2
b.__sizeof__()等效于sys.getsizeof(b)
palash

1
round(getsizeof(a) / 1024 / 1024,2)获得MB
gies0r

13

nbytes字段将为您提供数组中所有元素的大小(以字节为单位)numpy.array

size_in_bytes = my_numpy_array.nbytes

请注意,这并不测量“数组对象的非元素属性”,因此,以字节为单位的实际大小可以比此大几个字节。


这个答案仍然会创建一个数组,因此我认为您的意思是“无需从列表转换为数组”。尽管GWW的答案确实是先创建一个列表,然后将其转换为数组,但这并不重要,因为OP已经具有数组了。至关重要的是如何首先获得阵列。有人可能会说它重塑了现有的阵列,因此也可以批评这种回答。
辩论

您好@Moot,感谢您的评论。问题是关于如何获取数组字节的大小。虽然我的代码片段首先创建了一个数组,但这仅是为了拥有一个可以执行的完整示例。我将编辑答案以强调这一点。
El Marce

1

在python笔记本中,我经常想过滤掉“悬空的numpy.ndarray”,特别是存储在的笔记本中_1_2等从未真正意味着活路。

我使用此代码来获取所有列表及其大小的列表。

不知道locals()或者globals()是更好地在这里。

import sys
import numpy
from humanize import naturalsize

for size, name in sorted(
    (value.nbytes, name)
    for name, value in locals().items()
    if isinstance(value, numpy.ndarray)):
  print("{:>30}: {:>8}".format(name, naturalsize(size)))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.