根据this SO和this PyTorch discussion,PyTorch的{{1}}函数仅适用于连续内存,而view
无效。在第二个链接中,作者甚至声称:
[{
reshape
]将在不连续的张量上引发错误。
但是张量何时具有不连续的内存?
答案 0 :(得分:2)
This是一个很好的答案,它在NumPy和PyTorch的上下文中解释了该主题,本质上是相同的。 PyTorch的文档通常不会提到函数输出是否(不)连续,这可以根据操作的类型(具有一定的经验和对实现的理解)来猜测。根据经验,大多数操作在构造新张量时都保持连续性。如果操作就地在阵列上工作并更改其跨度,则可能会看到不连续的输出。下面有几个例子
import torch
t = torch.randn(10, 10)
def check(ten):
print(ten.is_contiguous())
check(t) # True
# flip sets the stride to negative, but element j is still adjacent to
# element i, so it is contiguous
check(torch.flip(t, (0,))) # True
# if we take every 2nd element, adjacent elements in the resulting array
# are not adjacent in the input array
check(t[::2]) # False
# if we transpose, we lose contiguity, as in case of NumPy
check(t.transpose(0, 1)) # False
# if we transpose twice, we first lose and then regain contiguity
check(t.transpose(0, 1).transpose(0, 1)) # True
通常,如果您具有不连续的张量t
,则可以通过调用t = t.contiguous()
使它成为连续的。如果t
是连续的,则对t.contiguous()
的调用本质上是无操作的,因此您可以这样做,而不会冒很大的性能损失的风险。
答案 1 :(得分:1)
我认为您的标题contiguous memory
有点误导。据我了解,PyTorch中的contiguous
表示张量中的相邻元素实际上在内存中是否彼此相邻。让我们举一个简单的例子:
x = torch.tensor([[1, 2, 3], [4, 5, 6]]) # x is contiguous
y = torch.transpose(0, 1) # y is non-contiguous
根据documentation of tranpose()
:
返回张量,它是输入的转置版本。给定的尺寸dim0和dim1被交换。
生成的张量与输入张量共享其基础存储,因此更改其中一个的内容将更改另一个的内容。
使上面示例中的x
和y
共享相同的内存空间。但是,如果用is_contiguous()
检查它们的连续性,则会发现x
是连续的,而y
不是。现在,您会发现contiguity
没有引用contiguous memory
。
由于x
是连续的,因此x[0][0]
和x[0][1]
在内存中彼此相邻。但是y[0][0]
和y[0][1]
不是。这就是contiguous
的意思。