Skip to content

← Shapes and Strides step 1 of 9

Easy Primitives

Read the stride

A tensor is three things:

a buffer     a flat run of numbers in memory
a shape      how to pretend it has axes
a stride     how far to step, in elements, to move one along each axis

That is the whole data structure. Everything in this track is arithmetic on the last two, leaving the first alone.

Worked example

x = torch.arange(24).reshape(2, 3, 4)
x.shape    # (2, 3, 4)
x.stride() # (12, 4, 1)

Read it right to left. Moving one along the last axis steps 1 element, because neighbours on that axis are neighbours in memory. Moving one along the middle axis steps 4, because a whole row of 4 sits between them. Moving one along the first steps 12, because a whole 3 x 4 block does.

This layout, where each stride is the product of the sizes to its right, is what contiguous means. It is a property of the strides, not a property of being a real tensor.

Permuting does not move anything

y = x.permute(2, 0, 1)
y.shape    # (4, 2, 3)
y.stride() # (1, 12, 4)

The strides were reordered to match. Axis 0 of y was axis 2 of x, so it keeps stride 1. Nothing was read, nothing was written, and y points at the same buffer.

Notice y is no longer contiguous: its strides are not descending products. That is fine. Contiguity is a fact about layout, not about correctness.

Your task

def permuted_stride(shape: list[int], order: list[int]) -> list[int]

Given the shape of a freshly-created contiguous tensor and a permutation order, return the stride of tensor.permute(*order) as a list.

You may build the tensor and ask it. That is the intended solution: the point is to see the answer, not to derive it blind. The starter returns the original stride, which is right exactly when order changes nothing.