为什么需要Tensor.contiguous()
Tensor.contiguous()作用
Returns a contiguous in memory tensor containing the same data as self tensor. If self tensor is already in the specified memory format, this function returns the self tensor.
作用在官方文档里,描述的看似清晰但又模棱两可。例如x是一个Tensor,x.contiguous()
的作用就是返回一个在内存中连续的Tensor,其data与Tensorx
一致。如果源x本来就在内存中连续的话,那就返回其本身。
为什么要有Tensor.contiguous()?
Reference: StackOverflow–Why do we need contiguous?
在PyTorch中,有些对Tensor的操作并不实际改变tensor的内容,而只是改变如何根据索引检索到tensor的byte location的方式。
这些操作有:
narrow()
,view()
,expand()
,transpose()
,permute()
例如: 当我们调用transpose()
时,PyTorch并不会生成一个具有新的layout(大概可以翻译为布局)的新tensor。该操作仅仅改变了tensor中的meta information
(元信息),所以offset和stride可以正确作用于新的shape。但是转置后的tensor和源tensor在事实上是共享同一块内存空间的。
>>> x = torch.randn(3,2)
>>> print(x)
tensor([[ 0.9181, 1.4266],
[-0.1432, -0.7514],
[ 0.9809, -0.5079]])
>>> print(x[0,0])
tensor(0.9181)
>>> y = x.transpose(1,0)
>>> print(y)
tensor([[ 0.9181, -0.1432, 0.9809],
[ 1.4266, -0.7514, -0.5079]])
>>> print(y[0,0])
tensor(0.9181)
这就是contiguous
的来源。上述例子中x
是连续的,但是y
不是,因为y
的内存布局与从头开始新建一个与y
shape相同的tensor的内存布局不同。
需要注意的是,contiguous这个单词有点被误解了,它并不是指tensor的内容在内存块上不连续。字节仍然是分配在同一个内存块上的,问题在于其元素之间的顺序order。
而当我们调用contiguous()
时,实际上它是会复制一个张量,同时元素之间在内存上的顺序与从零开始新建的相同shape的张量一致。