01 · THE QUESTION DRAM ASKS
Not "how much" — "how"
Global memory is where every kernel's data lives, and it is slower than the cores by orders of magnitude. Day 01's answer was supply: keep enough warps in flight and the chip stays busy while lanes wait. But that answer has a fine print, and it's the difference between a kernel that flies and one that crawls with identical math.
When a warp reads global memory, the hardware doesn't fetch 32 separate values. It fetches 128-byte chunks — memory moves in transactions, and whatever a warp's 32 lanes actually needed, the transaction is what gets delivered. If the 32 addresses happen to be contiguous, one transaction covers them all and every byte is used. If they're scattered, the hardware fetches one transaction per distinct chunk, and most of each delivery is thrown away unread.
Same instruction. Same values loaded. Same warp. The pattern alone decides whether your kernel used the memory system at 100% or 3%.
02 · THE EXPLORABLE
Same 32 floats, three access patterns
Each row below is one warp reading 32 floats. The colored cells are what the lanes actually requested; the bracketed strips are the 128B transactions the hardware had to deliver. Flip between the patterns and count the deliveries.
TRANSACTIONS
1
BYTES DELIVERED
128
BANDWIDTH USED
100%
one transaction, every byte used. this is the fast path.
simplified: real transactions are 32B sectors grouped into up to 128B per warp request · counts shown for the common case
03 · WHERE DIVERGENCE HIDES
The pattern is your code's fault
Nobody writes strided reads on purpose. They arrive disguised as reasonable-looking data structures. A struct of arrays would give each warp one clean consecutive sweep; an array of structs — the default in most languages — scatters the same warp across memory by the size of the whole struct. Same loop, same math, the pattern is decided by how you laid out your types.
The fix list is short and worth memorizing: keep per-thread access consecutive, organize hot data as arrays rather than interleaved records, pad anything that misaligns, and when a warp must touch scattered data, stage it through shared memory (day 08) so the ugly pattern happens once instead of 46 times.
And notice the connection to last week: divergence was the branch version of this lesson, coalescing is the memory version. In both cases the warp's shape — what its 32 lanes do relative to each other — is the performance.
- 01Memory moves in transactions. A warp's 32 requests are delivered as one or more 128B chunks. Pattern decides how many.
- 02Consecutive is one transaction. Lane i reading element i uses 100% of the delivery. Strided patterns discard most of it.
- 03Layout beats cleverness. Arrays of data (SoA) coalesce; interleaved records (AoS) stride. Choose the layout before the loop.
- 04Shared memory is the fix-up. When patterns can't be clean, stage through shared memory so the ugly access happens once per block.
That closes week one: the mental model, the hardware, the hierarchy, the warp, its failure mode, its supply, and its memory. Week two goes hands-on — day 08 is shared memory's own chapter, then the code starts.