NumPy Memory Layout: C-Contiguous vs Fortran-Contiguous

NumPy stores multidimensional arrays as flat, one-dimensional blocks of computer memory, utilizing specific ordering conventions to map multi-axis indices to sequential memory addresses. The two primary conventions are C-contiguous (row-major) and Fortran-contiguous (column-major) order. This article explains the fundamental differences between these two layouts, illustrates how they store data linearly, examines their impact on computational performance, and demonstrates how to inspect and modify them in code.

Understanding Row-Major vs. Column-Major Order

Computer memory is inherently linear and one-dimensional. When NumPy creates a multidimensional array (such as a 2D matrix), it must flatten that data into a single continuous sequence of bytes.

Memory Layout Example

Consider the following 2x3 matrix:

[[1, 2, 3],
 [4, 5, 6]]

The underlying linear memory storage depends entirely on the selected order:

Performance Implications

The memory layout directly affects cache utilization and execution speed due to CPU spatial locality. When a CPU reads a value from RAM, it also fetches adjacent values into its high-speed cache line.

Accessing an array contrary to its memory layout causes frequent cache misses, which drastically reduces throughput for large datasets.

Checking and Changing Memory Layout in NumPy

You can inspect an array's layout by checking its .flags attribute:

import numpy as np

# Create a default C-contiguous array
c_arr = np.array([[1, 2, 3], [4, 5, 6]], order='C')
print(c_arr.flags['C_CONTIGUOUS'])  # True
print(c_arr.flags['F_CONTIGUOUS'])  # False

# Create a Fortran-contiguous array
f_arr = np.array([[1, 2, 3], [4, 5, 6]], order='F')
print(f_arr.flags['C_CONTIGUOUS'])  # False
print(f_arr.flags['F_CONTIGUOUS'])  # True

Common array operations, such as transposition (arr.T), do not copy data; instead, they alter the array's strides. Transposing a C-contiguous array yields an array that behaves as Fortran-contiguous.

To explicitly convert an array into a specific contiguous memory layout, use np.ascontiguousarray() for C order or np.asfortranarray() for Fortran order:

# Convert to C-contiguous memory
c_converted = np.ascontiguousarray(f_arr)

# Convert to Fortran-contiguous memory
f_converted = np.asfortranarray(c_arr)