我试图深入了解PyTorch Tensor内存模型的工作原理。
# input numpy array
In [91]: arr = np.arange(10, dtype=float32).reshape(5, 2)
# input tensors in two different ways
In [92]: t1, t2 = torch.Tensor(arr), torch.from_numpy(arr)
# their types
In [93]: type(arr), type(t1), type(t2)
Out[93]: (numpy.ndarray, torch.FloatTensor, torch.FloatTensor)
# ndarray
In [94]: arr
Out[94]:
array([[ 0., 1.],
[ 2., 3.],
[ 4., 5.],
[ 6., 7.],
[ 8., 9.]], dtype=float32)
我知道PyTorchTensor * 共享NumPy ndarrays的内存缓冲区 *。因此,改变一个将反映在另一个。所以,这里我切片并更新Tensort2
中的一些值
In [98]: t2[:, 1] = 23.0
正如预期的那样,它在t2
和arr
中更新,因为它们共享相同的内存缓冲区。
In [99]: t2
Out[99]:
0 23
2 23
4 23
6 23
8 23
[torch.FloatTensor of size 5x2]
In [101]: arr
Out[101]:
array([[ 0., 23.],
[ 2., 23.],
[ 4., 23.],
[ 6., 23.],
[ 8., 23.]], dtype=float32)
但是,t1
也更新了。请记住,t1
是使用torch.Tensor()
构造的,而t2
是使用torch.from_numpy()
构造的
In [100]: t1
Out[100]:
0 23
2 23
4 23
6 23
8 23
[torch.FloatTensor of size 5x2]
因此,无论我们使用torch.from_numpy()
还是torch.Tensor()
从ndarray构造Tensor,所有这样的Tensor和ndarray共享相同的内存缓冲区。
基于这种理解,我的问题是,当torch.Tensor()
可以完成这项工作时,为什么要存在一个专用函数torch.from_numpy()
?
我看了PyTorch文档,但它没有提到任何关于这一点的事情。任何想法/建议?
5条答案
按热度按时间im9ewurl1#
from_numpy()
自动继承输入数组dtype
。另一方面,torch.Tensor
是torch.FloatTensor
的别名。因此,如果将
int64
数组传递给torch.Tensor
,输出Tensor是浮点Tensor,它们不会共享存储。torch.from_numpy
会像预期的那样提供torch.LongTensor
。lmyy7pcs2#
在Pytorch中构建Tensor的推荐方法是使用以下两个工厂函数:
torch.tensor
和torch.as_tensor
。torch.tensor
始终复制数据。例如,torch.tensor(x)
等价于x.clone().detach()
。torch.as_tensor
总是尝试避免数据的副本。as_tensor
避免复制数据的一种情况是,原始数据是一个numpy数组。zd287kbt3#
这来自
_torch_docs.py
;这里也有可能讨论“为什么”。引用
numpy
文档:不同的
ndarrays
可以共享相同的数据,因此在一个ndarray中所做的更改可能在另一个ndarray中可见。也就是说,ndarray
可以是另一个ndarray
的“视图”,它所引用的数据由“基础”ndarray
负责。Pytorch
docs
:如果给定
numpy.ndarray
、torch.Tensor
或torch.Storage
,则返回共享相同数据的新Tensor。如果给定了一个Python序列,则会从序列的副本创建一个新的Tensor。omjgkv6w4#
答案中没有人提到的是,NumPy数组和torchTensor的问题**“共享相同的内存”**只发生在你在CPU上运行代码时,但如果你在GPU上运行,如下代码每个NumPy,Tensor将有它的内存位置
输出
编辑
需要说明的是,NumPy数组和PyTorchTensor之间的内存共享只有在它们都位于CPU内存中时才会发生,但这种共享不会扩展到GPU内存。
当数据移动到GPU时,会为GPU上的Tensor分配新的内存,对CPU上原始NumPy数组所做的更改不会反映在GPUTensor中,反之亦然。
CPU内存:
当两者都在CPU内存中时,NumPy数组和PyTorchTensor之间可以发生内存共享。
对其中一个所做的更改将反映在另一个中,因为它们共享内存。
GPU内存:
当NumPy阵列和PyTorchTensor在GPU上时,它们之间不会发生内存共享。
对原始数组的任何更改都不会影响GPU上的Tensor,反之亦然。
CPU示例
输出CPU
GPU示例
输出GPU
oxalkeyp5#
我试着做你说的,它的工作如预期:Torch 1.8.1、Numpy 1.20.1、python 3.8.5
所有变量现在都具有与预期相同的值:
From_numpy使用与np变量相同的底层内存。因此,更改np或.from_numpy变量会相互影响,但不会影响Tensor变量。但是对y_t的更改只影响它本身,而不影响numpy或from_numpy变量。
当前输出:
不知道这是否是早期版本的问题?