【问题标题】:Difference between list and NumPy array memory size列表和 NumPy 数组内存大小的区别
【发布时间】:2021-05-15 17:26:01
【问题描述】:

我听说 Numpy 数组比 python 内置列表更有效,而且它们占用的内存空间更少。据我了解,Numpy 将这些对象彼此相邻地存储在内存中,而列表的 python 实现存储指向给定值的 8 个字节指针。但是,当我尝试在 jupyter notebook 中进行测试时,发现两个对象的大小相同。

import numpy as np
from sys import getsizeof
array = np.array([_ for _ in range(4)])
getsizeof(array), array

返回(128, array([0, 1, 2, 3])) 同:

l = list([_ for _ in range(4)])
getsizeof(l), l

(128, [0, 1, 2, 3])

您能否提供任何明确的示例来说明如何在 jupyter notebook 中显示?

【问题讨论】:

  • 使用 NumPy 数组的主要好处应该是更小的内存消耗和更好的运行时行为。 Refer Here

标签: python arrays list numpy


【解决方案1】:

getsizeof 不是衡量内存使用的好方法,尤其是列表。正如您所注意到的,该列表有一个指针缓冲区,指向内存中其他地方的对象。 getsizeof 记录了缓冲区的大小,但没有告诉我们有关对象的任何信息。

In [66]: list(range(4))
Out[66]: [0, 1, 2, 3]

列表有它的基本对象存储,加上带有 4 个指针的缓冲区(加上一些增长空间)。这些数字存储在其他地方。在这种情况下,数字很小,并且已经由解释器创建和缓存。所以他们的存储不会增加任何东西。但是每次使用都会创建更大的数字(和浮点数),并占用空间。列表也可以包含任何内容,例如指向其他列表的指针、字符串或字典等。

In [67]: arr = np.array([i for i in range(4)])   # via list
In [68]: arr
Out[68]: array([0, 1, 2, 3])
In [69]: np.array(range(4))            # more direct
Out[69]: array([0, 1, 2, 3])
In [70]: np.arange(4)
Out[70]: array([0, 1, 2, 3])           # faster

arr 也有一个基本的对象存储,具有形状和 dtype 等属性。它也有一个数据缓冲区,但是对于像这样的数字 dtype,该缓冲区具有实际数值(8 字节整数),而不是指向 Python 整数对象的指针。

In [71]: arr.nbytes
Out[71]: 32

该数据缓冲区仅占用 32 个字节 - 4*8。

对于这个小例子,getsizeof 返回相同的东西并不奇怪。基本对象存储比存储 4 个值的位置更重要。在处理 1000 个值和多维数组时,内存使用会显着不同。

但更重要的是计算速度。使用数组,您可以执行arr+1arr.sum() 之类的操作。它们在编译后的代码中运行,并且速度非常快。类似的列表操作必须以较慢的 Python 速度进行迭代,尽管指针、获取值等。但是对数组进行相同类型的迭代甚至更慢。

作为一般规则,如果您从列表开始,并进行 append 和列表推导等列表操作,最好坚持使用它们。

但是,如果您可以创建一次数组,或者从其他数组创建,然后使用numpy 方法,您将获得 10 倍的速度提升。数组确实更快,但前提是您以正确的方式使用它们。它们不是列表的简单替代品。

【讨论】:

    【解决方案2】:

    NumPy 数组在数组对象头上有一般数组信息(如形状、数据类型等)。所有值都存储在连续的内存块中。但是列表为每个新对象分配新的内存块并存储它们的指针。因此,当您迭代时,您并没有直接在内存上进行迭代。您正在迭代指针。因此,当您处理大数据时,它并不方便。这是一个例子:

    import sys
    import numpy as np
    
    random_values_numpy=np.arange(1000)
    random_values=range(1000)  
    #Numpy
    print(random_values_numpy.itemsize)
    print(random_values_numpy.size*random_values_numpy.itemsize)  
    #PyList
    print(sys.getsizeof(random_values))
    print(sys.getsizeof(random_values)*len(random_values))
    

    【讨论】:

      猜你喜欢
      • 2016-05-25
      • 2021-11-18
      • 2023-04-01
      • 2013-09-25
      • 1970-01-01
      • 2020-01-31
      • 1970-01-01
      • 2019-02-18
      相关资源
      最近更新 更多