В PyTorch, что заставляет тензор иметь несмежную память? - PullRequest
0 голосов
/ 08 января 2019

Согласно это SO и это обсуждение PyTorch , функция PyTorch view работает только для непрерывной памяти, а reshape - нет. Во второй ссылке автор даже заявляет:

[view] вызовет ошибку для несмежного тензора.

Но когда тензор имеет несмежную память?

Ответы [ 2 ]

0 голосов
/ 10 июля 2019

Я думаю, что ваш заголовок contiguous memory немного вводит в заблуждение. Как я понимаю, contiguous в PyTorch означает, что соседние элементы в тензоре фактически находятся рядом друг с другом в памяти. Давайте рассмотрим простой пример:

x = torch.tensor([[1, 2, 3], [4, 5, 6]]) # x is contiguous
y = torch.transpose(0, 1) # y is non-contiguous

Согласно документации 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.

0 голосов
/ 08 января 2019

Это - очень хороший ответ, который объясняет тему в контексте NumPy. 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() по сути является запретом, так что вы можете сделать это, не рискуя большим ударом по производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...