【问题标题】:Numpy | hex(id()) vs. .data麻木 |十六进制(id())与.data
【发布时间】:2022-01-13 10:22:26
【问题描述】:

我有两天一直在处理的两个问题:

如果我想为一个 numpy 对象 adarray 确定对象的内存地址和使用 numpy 方法 .array 的元素,一次使用普通的 python 函数 hex(id()) 我得到不同的地址。 使用 hex(id()) 它变得非常奇怪。有时元素会得到相同的地址,有时会得到不同的地址。

import numpy as np
y = np.array([0,1,2,3])
print(y.data)
print(y[0].data)
print(y[1].data)
print(y[2].data)
print(y[3].data)
print(hex(id(y[0])))
print(hex(id(y[1])))
print(hex(id(y[2])))
print(hex(id(y[3])))

结果是:

<memory at 0x7f9aaa22d870>
<memory at 0x7f9aaa1bd940>
<memory at 0x7f9aaa1bd940>
<memory at 0x7f9aaa1bd940>
<memory at 0x7f9aaa1bd940>
0x7f9aaa31e030

with hex((id))
0x7f9aaa1c0750
0x7f9aaa1c0730
0x7f9aaa1c0130
0x7f9aaa1c0750

【问题讨论】:

    标签: python numpy memory multidimensional-array hex


    【解决方案1】:

    这些结果中的大多数并不代表您的想法,因为 NumPy 内存布局的工作方式与您的想法不同。

    NumPy 数组对象不是它的数据缓冲区。数据缓冲区是独立的。有了数组所需的所有元数据,数组就不可能真正成为它的数据缓冲区,并且由于 NumPy 如何大量使用数组视图,数组也不可能直接包含其缓冲区。许多数组可以共享同一个数据缓冲区,或者具有重叠的数据缓冲区。

    一个 NumPy 数组对象包含一些元数据和一些指针,其中一个指向它的缓冲区。如果你做了print(hex(id(y))),你就会得到数组对象本身的地址。使用print(y.data),您打印一个代表数组数据缓冲区的memoryview 对象,“at 0x...”给出缓冲区的地址。


    当您执行y[0] 时,这并不是真正的数组元素。这是一个新的array scalar 对象,表示一个不可变标量,其值取自y 的第一个索引。它确实直接引用用于y的第一个元素的内存,因为当有人这样做时

    x = y[0]
    y[0] = 1
    

    他们不希望y[0] = 1 分配影响x

    数组标量有自己的地址和自己的数据缓冲区,与数组标量本身分开。数组标量的生命周期非常短,因此如果 y[0] 的生命周期在您检索 y[1] 之前结束,y[0]y[1] 可能最终使用相同的内存。他们没有必须使用相同的内存,但他们可以。

    当您执行print(hex(id(y[0]))) 时,您正在打印数组标量的地址。当您执行print(y[0].data) 时,您正在打印一个表示数组标量数据缓冲区的内存视图。


    话虽如此,对于这些内存地址几乎没有任何用处,尤其是在您不编写 C 扩展的情况下。如果您正在编写 C 扩展,那么您可能仍然不应该直接使用这些地址中的任何一个。 Cython 比直接写 C 代码方便多了。如果您确实想编写 C 来与 NumPy 进行交互,那么您需要更深入地了解 NumPy 数组是如何工作的,您应该阅读NumPy C API docs

    【讨论】:

      猜你喜欢
      • 2011-06-28
      • 2021-07-25
      • 2011-10-11
      • 2010-12-16
      • 2018-07-26
      • 2011-12-09
      • 2014-08-24
      • 2014-04-20
      相关资源
      最近更新 更多