Skip to content

← Shapes and Strides step 7 of 9

Medium Primitives

The third number in a tensor

A tensor is a buffer, a shape and a stride. There is a fourth number, and it is the one that catches people writing exactly the checks this course grades on.

v = torch.arange(10)
s = v[3:7]

s.storage_offset()   # 3

s shares v‘s buffer. It just does not start at the beginning of it. The offset says how many elements in the first element sits.

Why this matters to you specifically

data_ptr() returns the address of the first element, so it moves with the offset:

s.data_ptr() == v.data_ptr()                                  False
s.untyped_storage().data_ptr() == v.untyped_storage().data_ptr()  True

The first line is the check almost everyone writes, and it calls a genuine view a copy. It is wrong for v[3:7], for m[:, 2], and for every other view that does not begin at element zero. The course grades on the second form for this reason, and now so should you.

Column selection is the common case

m = torch.arange(20).reshape(4, 5)
col = m[:, 2]

col.storage_offset()   # 2
col.stride()           # (5,)
col.tolist()           # [2, 7, 12, 17]

Four numbers, spread five apart, starting at index 2. That is a view of four elements over a buffer of twenty, and it allocates nothing.

Your task

def describe(x: torch.Tensor, start: int, stop: int) -> dict

Return a dictionary describing the slice x[start:stop] of a 1-D tensor:

{"offset": <storage_offset>, "stride": <first stride, as an int>, "shares": <bool>}

shares must be true whenever the slice really does share the buffer, which is every case here. Get it from the storage, not from data_ptr().

The starter uses data_ptr() and is right only when the slice starts at zero.