Skip to content

← Memory, Copies and In-Place step 1 of 6

Medium Primitives

Clone, detach, or both

These two are constantly confused and they answer different questions.

                  new buffer?    tracked by autograd?
x                      -                 yes
x.detach()             no                no
x.clone()              yes               yes
x.detach().clone()     yes               no

clone is about memory. New buffer, same values. It stays in the autograd graph: gradients flow back through it, and the clone has a grad_fn.

detach is about autograd. Same buffer, no graph. It shares storage with the original, so it is not a copy in any sense that protects you.

They are independent, which is why the fourth row exists and why you will write x.detach().clone() more often than either alone.

The trap

snapshot = x.detach()
train_step()               # mutates x in place somewhere
snapshot                   # changed too

detach reads like “take a copy for safekeeping” and does nothing of the kind. If anything writes to x through any view, snapshot sees it.

For logging a value, keeping an initial state, or storing something in a replay buffer, you want detach().clone(). detach() alone is right when you only need to stop gradient flow and the tensor is about to be read.

The other order

x.clone().detach() gives the same result and does slightly more work: it builds a graph node for the clone and then throws it away. PyTorch’s own warning message recommends detach().clone(), and the reason is exactly that.

Your task

def snapshot(x: torch.Tensor) -> torch.Tensor

Return a value equal to x that is safe to keep: it must not share storage with x, and it must not require gradients.