【问题标题】:how does memory allocation occur in numpy array?numpy 数组中的内存分配是如何发生的?
【发布时间】:2021-03-20 09:41:16
【问题描述】:
import numpy as np

a = np.arange(5)

for i in a:
    print("Id of {} : {} \n".format(i,id(i)))

>>

ID 为 0:2295176255984

ID 为 1:2295176255696

ID 为 2:2295176255984

ID 为 3:2295176255696

ID 为 4:2295176255984

我想了解 numpy 数组的元素是如何在内存中分配的,我理解这与 Python 数组看到输出的不同。

感谢任何帮助。

【问题讨论】:

标签: python numpy memory numpy-ndarray


【解决方案1】:
In [68]: arr = np.arange(5)
In [69]: arr
Out[69]: array([0, 1, 2, 3, 4])

查看 numpy 数组属性的一种方法是:

In [70]: arr.__array_interface__
Out[70]: 
{'data': (139628245945184, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (5,),
 'version': 3}

data 类似于其数据缓冲区的id,其中实际存储了值。我们不能在其他代码中使用这个数字,但它在检查 view 之类的东西时很有用。其余部分用于解释这些值。

arrmemory 是一个 40 字节长 (5*8) 的 c 数组。那在哪里对我们来说并不重要。 arr 中的任何 view 都将使用相同的数据缓冲区。 copy 将拥有自己的数据缓冲区。

在数组上迭代就像是一个一个地访问值:

In [71]: i = arr[1]
In [72]: i
Out[72]: 1
In [73]: type(i)
Out[73]: numpy.int64

i 不是对a 元素的引用。它是具有相同值的新对象。它很像一个 0d 数组,具有许多相同的属性,包括:

In [74]: i.__array_interface__
Out[74]: 
{'data': (25251568, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (),
 'version': 3,
 '__ref': array(1)}

这就是为什么在迭代中查看id 没有多大意义。这也是为什么在 numpy 数组上迭代比在列表上迭代慢的原因。我们强烈反对这样的迭代。

将其与列表进行对比,列表中的元素通过reference存储(在某种数据缓冲区中):

In [78]: a,b,c = 100,'b',{}
In [79]: id(a)
Out[79]: 9788064
In [80]: alist=[a,b,c]
In [81]: id(alist[0])
Out[81]: 9788064

该列表实际上包含a,或者如果您更喜欢对变量a 引用的同一对象的引用。请记住,Python 自始至终都是面向对象的。

总之,Python 列表包含引用。 Numpy 数组包含值,它自己的方法可以访问和操作这些值。有一个对象 dtype 确实包含引用,但我们不要去那里。

【讨论】:

    【解决方案2】:

    我是 Code with Mosh 的粉丝。他在他的 youtube 频道和 udemy 上教所有这些东西。我已经购买了他关于数据结构和算法的 udemy 课程,该课程深入探讨了事物的工作原理。 例如,在教授数组的同时,他展示了如何制作数组以了解其背后的基本概念。

    你可以看这里:https://www.youtube.com/watch?v=BBpAmxU_NQo

    如果您只想了解 NumPy 数组:

    首先我会告诉你不同之处:

    NumPy 和数组的区别

    Numpy 是 Python 中科学计算的核心库。它提供了一个高性能的多维数组对象和用于处理这些数组的工具。 NumPy 数组是一个值网格,所有值都具有相同的类型,并由非负整数元组索引。维数是数组的秩;数组的形状是一个整数元组,给出了数组沿每个维度的大小。

    Python 核心库提供了列表。列表相当于 Python 中的数组,但可以调整大小并且可以包含不同类型的元素。

    一个常见的初学者问题是这里的真正区别是什么。答案是性能。 Numpy 数据结构在以下方面表现更好:

    大小 - Numpy 数据结构占用的空间更少 性能 - 他们需要速度并且比列表更快 功能 - SciPy 和 NumPy 具有优化的功能,例如内置的线性代数运算。

    另一个显着的关键区别在于它们如何存储和使用内存 内存

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

    对于 Python 列表 - 我们可以由此得出结论,对于每个新元素,我们需要另外 8 个字节来引用新对象。新的整数对象本身占用 28 个字节。

    NumPy 占用的空间更少。这意味着 NumPy 中长度为“n”的任意整数数组需要

    如果你很好奇并希望我证明 NumPy 确实需要更少的时间:

    # importing required packages 
    import numpy 
    import time 
    
    # size of arrays and lists 
    size = 1000000
    
    # declaring lists 
    list1 = range(size) 
    list2 = range(size) 
    
    # declaring arrays 
    array1 = numpy.arange(size) 
    array2 = numpy.arange(size) 
    
    # capturing time before the multiplication of Python lists 
    initialTime = time.time() 
    
    # multiplying elements of both the lists and stored in another list 
    resultantList = [(a * b) for a, b in zip(list1, list2)] 
    
    # calculating execution time 
    print("Time taken by Lists to perform multiplication:", 
        (time.time() - initialTime), 
        "seconds") 
    
    # capturing time before the multiplication of Numpy arrays 
    initialTime = time.time() 
    
    # multiplying elements of both the Numpy arrays and stored in another Numpy array 
    resultantArray = array1 * array2 
    
    # calculating execution time 
    print("Time taken by NumPy Arrays to perform multiplication:", 
        (time.time() - initialTime), 
        "seconds") 
    

    输出:

    Time taken by Lists : 0.15030384063720703 seconds
    Time taken by NumPy Arrays : 0.005921125411987305 seconds
    

    等等..还有一个很大的缺点:

    需要连续分配内存 - 插入和删除操作可能会变得昂贵,因为数据存储在连续的内存位置,因为移位需要移位。

    如果您想了解有关 numpy 的更多信息: https://www.educba.com/introduction-to-numpy/

    以后你可以感谢我!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-03
      • 1970-01-01
      • 2011-03-23
      • 1970-01-01
      相关资源
      最近更新 更多