【问题标题】:numpy ndarray object much bigger than listsnumpy ndarray 对象比列表大得多
【发布时间】:2022-01-14 10:24:12
【问题描述】:

我现在已经更详细地处理了 numpy 数组。您总是读到 numpy ndarray 使用较少的内存,但如果您查看总内存消耗,ndarray 比列表大得多。

在列表中,我们有大小为 28 字节的 int 对象,但在 numpy 数组中,我们有大小为 32 字节的 numpy.int64 对象。

所以我只是不明白为什么他们说 numpy 对象使用更少的内存,因为 numpy.int64 对象比 int 对象大四个字节。

import numpy as np

from sys import getsizeof

def is_iterable(p_object):
    try:
        iter(p_object)
    except TypeError: 
        return False
    return True

def get_total_size(element, size):
  if not is_iterable(element):
    return size + getsizeof(element)
  size = size + getsizeof(element)
  for new_element in element:
    size = get_total_size(new_element, size)
  return size


if __name__ == "__main__":
  x_list = list(range(100))
  x_array = np.array(x_list)


  print("x_list:")
  print("A list with object references consumes in memory " + str(getsizeof(x_list)) + " Byte(s)")
  print("A list of object references and all objects consumed in memory " + str(get_total_size(x_list, 0)) + " Byte(s)")

  print("")

  print("Numpy-Array:")
  print("A ndarray object references consumes in memory " + str(getsizeof(x_array)) + " Byte(s)")
  print("A ndarray of object references and all objects consumed in memory  " + str(get_total_size(x_array, 0)) + " Byte(s)")

print("")
print("objecttype", type(x_array[1]), "size in bytes", getsizeof(x_array[1]), )
print("objecttype", type(x_list[1]), "size in bytes", getsizeof(x_list[1]), )

输出:

x_list:
A list with object references consumes in memory 1016 Byte(s)
A list of object references and all objects consumed in memory 3812 Byte(s)

Numpy-Array:
A ndarray object references consumes in memory 896 Byte(s)
A ndarray of object references and all objects consumed in memory  4096 Byte(s)

objecttype <class 'numpy.int64'> size in bytes 32
objecttype <class 'int'> size in bytes 28

【问题讨论】:

  • 这能回答你的问题吗? Python3 numpy array size compare to list
  • 您的数组不是对象 dtype,因此不需要添加“引用”。您的列表处理没问题(比大多数都好),但您可能还想检查浮点数或更大的整数。但是内存使用并不是 numpy 的主要优势。计算速度是(如果做得对的话)。
  • Julien 的参考资料可能是您问题的答案,但无论如何您都可以使用x_array = np.array(x_list, dtype=np.int32)
  • 您没有正确获取对象的内存消耗。重要的是,objecttype &lt;class 'numpy.int64'&gt; size in bytes 32 无关紧要。 numpy.ndarray 对象本质上是原始数组的面向对象的包装器。要获取底层缓冲区的大小,您只需要x_array.nbytes

标签: python arrays numpy


【解决方案1】:
In [144]: alist = list(range(100))
In [145]: getsizeof(alist)
Out[145]: 856

大多数getsizeof 问题只使用这个基数,忽略引用。

In [146]: get_total_size(alist,0)
Out[146]: 3652

单个整数的大小可以变化:

In [148]: getsizeof(50)
Out[148]: 28
In [149]: getsizeof(220000000000000000)
Out[149]: 32

100*28+856= 3656 足够接近。小于 256 的整数是预先分配的,因此您的列表不会将它们添加到总内存使用量中。但这是一个小细节。

对于具有数字 dtype 的数组,我们不需要检查不存在的“引用”

In [152]: arr = np.array(alist)
In [153]: getsizeof(arr)
Out[153]: 904
In [154]: arr.nbytes
Out[154]: 800

它的数据缓冲区中有 800 个字节,大约 100 个字节用于“开销”。那是100*8,每个int64 数字8 个字节。其他 dtype 可能有不同的元素大小。

对于对象 dtype 数组,添加引用很重要:

In [155]: arr = np.array(alist,object)
In [156]: getsizeof(arr)
Out[156]: 904
In [158]: get_total_size(arr,0)
Out[158]: 3700     # 2800+900

此数组引用与 alist 相同的整数。

您在数字 dtype 数组上的 get_total_size 发现

In [164]: getsizeof(np.int64(50))
Out[164]: 32

但数组不会“存储”其中的 100 个。 32 是其值的 8 个字节和 24 个开销。那是“未装箱”的对象,而不是存储的值。

【讨论】:

    猜你喜欢
    • 2022-09-30
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 2018-07-28
    • 2021-09-26
    • 2015-08-07
    • 2019-05-09
    相关资源
    最近更新 更多