Module 6 · Lesson 1
Memory Layout: Strides & Order
.strides tells you how many bytes to step to move one position along
each axis. For a C-order (row-major, the default) (2, 3) array of
float64, moving one column over costs 8 bytes, but moving one row down
costs 3 * 8 = 24 bytes — because rows are stored one after another in
memory.
Fortran order (order="F") stores columns contiguously instead — the
strides flip. This is why .T (transpose) is instant and never copies data:
it just swaps the strides and shape, leaving the underlying buffer alone.
That also means a transposed array is usually not C-contiguous anymore.
When an algorithm (or a library written in C) genuinely needs a contiguous
buffer, use np.ascontiguousarray(arr) — it returns arr itself if it’s
already contiguous, and a real copy only if it isn’t.
a = np.arange(6, dtype=np.float64).reshape(2, 3)
print("C-order strides:", a.strides) # (24, 8): 24 bytes per row, 8 per column
print("is C-contiguous:", a.flags["C_CONTIGUOUS"])
at = a.T
print("\ntransposed strides:", at.strides) # strides just swapped, no copy
print("transpose is C-contiguous:", at.flags["C_CONTIGUOUS"])
print("transpose shares memory with a:", np.shares_memory(a, at))
f = np.asfortranarray(a)
print("\nFortran-order strides:", f.strides)
Output:
C-order strides: (24, 8)
is C-contiguous: True
transposed strides: (8, 24)
transpose is C-contiguous: False
transpose shares memory with a: True
Fortran-order strides: (8, 16)
Spot the view
Write second_row_view(matrix) that returns a view (not a copy) of row
index 1 of a 2-D array, using basic slicing.
💡 Hint
Plain slicing with matrix[1] (or matrix[1, :]) already returns a view — no .copy() needed.
✅ Solution
def second_row_view(matrix):
return matrix[1]
Force a contiguous copy
Write ensure_contiguous(arr) that returns a C-contiguous version of
arr. If arr is already C-contiguous, return it unchanged (same
underlying buffer); otherwise return a new, C-contiguous array with the
same shape and values.
💡 Hint
np.ascontiguousarray does exactly this: no-op copy if already contiguous, real copy otherwise.
✅ Solution
def ensure_contiguous(arr):
return np.ascontiguousarray(arr)