Skip to content

← Shapes and Strides step 2 of 9

Medium Primitives

When reshape needs a copy

Jump to the task

view and reshape can return the same values, but differ when the requested shape cannot use the existing storage layout.

Operation If the requested shape cannot share storage
x.view(shape) Raises an error
x.reshape(shape) Copies values into a suitable layout

Both still require a valid shape with the same number of elements. reshape can raise too, for example when asked to turn six elements into shape (4, 2). Its fallback handles incompatible strides, not every error.

Flattening a transposed matrix

import torch

m = torch.arange(12).reshape(3, 4)
t = m.t()
flat = t.reshape(-1)
print(flat.tolist())  # [0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11]
print(flat.untyped_storage().data_ptr() == m.untyped_storage().data_ptr())  # False

Reading t row by row visits storage positions 0, 4, 8, then jumps back to 1, 5, 9. No single stride describes that full sequence. t.view(-1) therefore raises, while t.reshape(-1) copies to produce the requested order.

Flattening the original contiguous m can share storage instead. A view still needs tensor metadata; it avoids allocating a new data buffer.

Transposed does not always mean copied

A transposed single row is still a contiguous column:

row = torch.arange(5).reshape(1, 5)
column = row.t()
flat = column.view(-1)
print(flat.tolist())  # [0, 1, 2, 3, 4]
print(flat.untyped_storage().data_ptr() == row.untyped_storage().data_ptr())  # True

Some noncontiguous tensors can also be flattened as views. The deciding factor is whether their strides support the requested shape, not whether a transpose occurred earlier.

Choose based on the requirement

Use view when sharing storage is required and an incompatible layout should be an error. Use reshape when a copy is acceptable if needed. Do not assume that reshape always copies or always shares; inspect the layout when storage behavior matters. flatten can likewise return the input, a view or a copy depending on the requested flattening.

Your task

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

Return the supplied strided 2-D tensor flattened into one dimension in logical row order. Handle both contiguous matrices and their transposes. Share storage when the tested flattening can be represented as a view; otherwise return a copy.

The harness reports values and storage sharing. The transposed matrices with both dimensions greater than one require copies. The single-row and single-column cases can still share storage. The starter uses view, so it raises on the two test cases that need copies.