天天看点

为什么需要Tensor.contiguous()? PyTorch中Tensor.contiguous()作用分析为什么需要Tensor.contiguous()

为什么需要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与Tensor

x

一致。如果源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的张量一致。

继续阅读