python - 列表和 NumPy 数组内存大小的区别
问题描述
我听说 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 中展示它吗?
解决方案
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+1
或arr.sum()
。它们在编译后的代码中运行,并且速度非常快。类似的列表操作必须以较慢的 Python 速度进行迭代,尽管指针、获取值等。但是对数组进行相同类型的迭代甚至更慢。
作为一般规则,如果您从列表开始,然后执行列表操作(如append
和列表推导式),最好坚持使用它们。
但是,如果您可以创建一次数组,或者从其他数组创建,然后使用numpy
方法,您将获得 10 倍的速度提升。数组确实更快,但前提是您以正确的方式使用它们。它们不是列表的简单替代品。
推荐阅读
- java - Kotlin:使用“val authority”覆盖名为“getAuthorities()”的接口方法
- javascript - 从 firebase 回调中赋值
- javascript - Magento 2 淘汰赛 XML->PHTML->JS->HTML
- javascript - 显示隐藏段落取决于 div 计数
- c++ - 在 C++ 中更改 struct 内部元素的方法?
- powerbi - power bi 中的链接报表
- symfony - 如何在多个级别上更新实体及其关系?
- python - 调整大小未知的张量流图像
- c++ - C++ 将常量映射到值
- vb.net - 无法打开 PDF。某些东西使此 PDF 无法打开。使用 VB.NET 打印表单