Pytorch 内存模型:"torch.from_numpy()" 是如何工作的?
Pytorch memory model: how does "torch.from_numpy()" work?
我正在努力深入了解 torch.from_numpy()
的工作原理。
import numpy as np
import torch
arr = np.zeros((3, 3), dtype=np.float32)
t = torch.from_numpy(arr)
print("arr: {0}\nt: {1}\n".format(arr, t))
arr[0,0]=1
print("arr: {0}\nt: {1}\n".format(arr, t))
print("id(arr): {0}\nid(t): {1}".format(id(arr), id(t)))
输出如下所示:
arr: [[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
t: tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
arr: [[1. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
t: tensor([[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
id(arr): 2360964353040
id(t): 2360964352984
这是来自 torch.from_numpy()
:
的文档的一部分
from_numpy(ndarray) -> Tensor
Creates a :class:Tensor
from a :class:numpy.ndarray
.
The returned tensor and :attr:ndarray
share the same memory. Modifications to
the tensor will be reflected in the :attr:ndarray
and vice versa. The returned
tensor is not resizable.
这取自 id()
的文档:
Return the identity of an object.
This is guaranteed to be unique among simultaneously existing objects.
(CPython uses the object's memory address.)
那么问题来了:
既然ndarrayarr
和张量t
共享同一个内存,为什么它们的内存地址不同?
任何 ideas/suggestions?
是的,t
和 arr
是位于不同内存区域的不同 Python 对象(因此不同 id
),但都指向相同的内存地址,其中包含数据(连续(通常)C 数组)。
numpy
使用绑定到 Python
函数的 C
代码在此区域上运行,torch
也是如此(但使用 C++
)。 id()
不知道数据本身的内存地址,只知道它是 "wrappers"。
编辑: 当您分配 b = a
时(假设 a
是 np.array
),两者都是对相同 [=78= 的引用]包装器(np.ndarray
)。换句话说,它们是同一个对象,但名称不同。
这就是 Python 的分配方式,请参阅 documentation。以下所有情况也会 return True
:
import torch
import numpy as np
tensor = torch.tensor([1,2,3])
tensor2 = tensor
id(tensor) == id(tensor2)
arr = np.array([1, 2, 3, 4, 5])
arr2 = arr
id(arr) == id(arr2)
some_str = "abba"
other_str = some_str
id(some_str) == id(other_str)
value = 0
value2 = value
id(value) == id(value2)
现在,当您在 np.ndarray
上使用 torch.from_numpy
时,您有两个不同 类 的对象(torch.Tensor
和原始 np.ndarray
)。由于它们属于不同类型,因此它们不能具有相同的 id
。可以将此案例视为类似于以下案例:
value = 3
string_value = str(3)
id(value) == id(string_value)
这里很直观,string_value
和 value
是位于不同内存位置的两个不同对象。
编辑 2:
总而言之,Python对象和底层C数组的概念必须分开。 id()
不知道 C 绑定(怎么可能?),但它知道 Python 结构(torch.Tensor
、np.ndarray
)的内存地址。
在numpy
和torch.tensor
的情况下,您可能会遇到以下情况:
- 在 Python 级别上分开,但对数组使用相同的内存区域 (
torch.from_numpy
)
- 在 Python 级别和底层内存区域(一个
torch.tensor
和另一个 np.array
)分开。可以通过 from_numpy
后跟 clone()
或类似的深度复制操作来创建。
- 在 Python 级别和底层内存区域相同(例如,两个
torch.tensor
对象,一个引用另一个,如上所述)
我正在努力深入了解 torch.from_numpy()
的工作原理。
import numpy as np
import torch
arr = np.zeros((3, 3), dtype=np.float32)
t = torch.from_numpy(arr)
print("arr: {0}\nt: {1}\n".format(arr, t))
arr[0,0]=1
print("arr: {0}\nt: {1}\n".format(arr, t))
print("id(arr): {0}\nid(t): {1}".format(id(arr), id(t)))
输出如下所示:
arr: [[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
t: tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
arr: [[1. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
t: tensor([[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
id(arr): 2360964353040
id(t): 2360964352984
这是来自 torch.from_numpy()
:
from_numpy(ndarray) -> Tensor
Creates a :class:
Tensor
from a :class:numpy.ndarray
.The returned tensor and :attr:
ndarray
share the same memory. Modifications to the tensor will be reflected in the :attr:ndarray
and vice versa. The returned tensor is not resizable.
这取自 id()
的文档:
Return the identity of an object.
This is guaranteed to be unique among simultaneously existing objects. (CPython uses the object's memory address.)
那么问题来了:
既然ndarrayarr
和张量t
共享同一个内存,为什么它们的内存地址不同?
任何 ideas/suggestions?
是的,t
和 arr
是位于不同内存区域的不同 Python 对象(因此不同 id
),但都指向相同的内存地址,其中包含数据(连续(通常)C 数组)。
numpy
使用绑定到 Python
函数的 C
代码在此区域上运行,torch
也是如此(但使用 C++
)。 id()
不知道数据本身的内存地址,只知道它是 "wrappers"。
编辑: 当您分配 b = a
时(假设 a
是 np.array
),两者都是对相同 [=78= 的引用]包装器(np.ndarray
)。换句话说,它们是同一个对象,但名称不同。
这就是 Python 的分配方式,请参阅 documentation。以下所有情况也会 return True
:
import torch
import numpy as np
tensor = torch.tensor([1,2,3])
tensor2 = tensor
id(tensor) == id(tensor2)
arr = np.array([1, 2, 3, 4, 5])
arr2 = arr
id(arr) == id(arr2)
some_str = "abba"
other_str = some_str
id(some_str) == id(other_str)
value = 0
value2 = value
id(value) == id(value2)
现在,当您在 np.ndarray
上使用 torch.from_numpy
时,您有两个不同 类 的对象(torch.Tensor
和原始 np.ndarray
)。由于它们属于不同类型,因此它们不能具有相同的 id
。可以将此案例视为类似于以下案例:
value = 3
string_value = str(3)
id(value) == id(string_value)
这里很直观,string_value
和 value
是位于不同内存位置的两个不同对象。
编辑 2:
总而言之,Python对象和底层C数组的概念必须分开。 id()
不知道 C 绑定(怎么可能?),但它知道 Python 结构(torch.Tensor
、np.ndarray
)的内存地址。
在numpy
和torch.tensor
的情况下,您可能会遇到以下情况:
- 在 Python 级别上分开,但对数组使用相同的内存区域 (
torch.from_numpy
) - 在 Python 级别和底层内存区域(一个
torch.tensor
和另一个np.array
)分开。可以通过from_numpy
后跟clone()
或类似的深度复制操作来创建。 - 在 Python 级别和底层内存区域相同(例如,两个
torch.tensor
对象,一个引用另一个,如上所述)