Picture a bookcase full of vectors
A matrix is a stack of vectors. Each row (or column) can be sliced out as its own vector, but the whole bookcase has to occupy one contiguous chunk of memory. The choice of which dimension is contiguous is the layout.
GPU mantra: coalesce or die. When 32 neighboring threads in a warp read 32 contiguous addresses, the hardware satisfies them in one (or close to one) memory transaction. Break that pattern and bandwidth tanks.
| Layout | In-memory order | Best when |
|---|---|---|
| Row-major | Row elements adjacent (stride along columns is 1) | Threads stride across a row |
| Column-major | Column elements adjacent (stride along rows is 1) | Threads stride down a column (Fortran/cuBLAS) |
Reality check on RTX 4090, 4096×4096 FP32 row-sum:
- Row-major + threads scan rows (coalesced): 610 GB/s
- Column-major + threads scan rows (strided): 105 GB/s
That's a 6× swing caused entirely by access pattern.
Leading dimension (ld)
The 'leading dimension' is the stride between consecutive rows (or columns). For tightly packed matrices, ld == cols for row-major or ld == rows for column-major. But you'll often pad — ld > cols — to avoid memory bank conflicts. Every cuBLAS call takes lda, ldb, ldc for exactly this reason.