Skip to content

Memory Contiguity

Memory layout affects whether operations return views or copies.

C Contiguous

C-style row-major memory layout.

1. Row-Major Order

Array: [[0, 1, 2, 3],
        [4, 5, 6, 7],
        [8, 9, 10, 11]]

Memory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Elements are stored row by row.

2. NumPy Default

NumPy arrays are C-contiguous by default.

Fortran Contiguous

Fortran-style column-major memory layout.

1. Column-Major Order

Array: [[0, 1, 2, 3],
        [4, 5, 6, 7],
        [8, 9, 10, 11]]

Memory: [0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11]

Elements are stored column by column.

2. Transpose Effect

Transposing a C-contiguous array makes it Fortran-contiguous.

View Chain Example

Track memory sharing through operations.

1. Initial Array

import numpy as np

def main():
    x = np.arange(12)
    print(f"{id(x) = }")

if __name__ == "__main__":
    main()

2. Reshape (View)

import numpy as np

def main():
    x = np.arange(12)
    print(f"{id(x) = }")

    y = x.reshape(3, 4)  # view
    print(f"{id(y) = }")

    y[-1, -1] = -11
    print(f"{x = }")

if __name__ == "__main__":
    main()

x and y share the same memory block.

3. Transpose (View)

import numpy as np

def main():
    x = np.arange(12)
    print(f"{id(x) = }")

    y = x.reshape(3, 4)  # view
    print(f"{id(y) = }")

    z = y.T  # still a view
    print(f"{id(z) = }")

    z[-1, -1] = -11
    print(f"{x = }")

if __name__ == "__main__":
    main()

z still shares memory but interprets it column-wise.

Forced Copy

Non-contiguous arrays force copies when reshaped.

1. Copy Scenario

import numpy as np

def main():
    x = np.arange(12)
    print(f"{id(x) = }")

    y = x.reshape(3, 4)  # view
    print(f"{id(y) = }")

    z = y.T  # view (Fortran contiguous)
    print(f"{id(z) = }")

    w = z.reshape((-1,))  # COPY (must reorder data)
    print(f"{id(w) = }")

    w[-1] = -11
    print(f"{x = }")
    print(f"{y = }")
    print(f"{z = }")
    print(f"{w = }")

if __name__ == "__main__":
    main()

2. Why Copy Needed

z is Fortran-contiguous [0,4,8,1,5,9,2,6,10,3,7,11] in memory. Flattening to C-order requires reordering, forcing a copy.

3. Memory Independence

w has different id() and modifications don't affect x, y, z.

Checking Contiguity

Inspect array memory layout flags.

1. Flags Attribute

import numpy as np

x = np.arange(12).reshape(3, 4)
print(x.flags)

Output:

  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  ...

2. After Transpose

import numpy as np

x = np.arange(12).reshape(3, 4)
y = x.T
print(y.flags)

Output:

  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  ...

Best Practices

Guidelines for working with memory layout.

1. Be Aware

Know when operations return views vs copies.

2. Use id()

Track object identity to verify memory sharing.

3. Explicit Copy

When data integrity is critical, call .copy() explicitly.

4. Check flags

Use .flags to inspect contiguity when debugging.