Chapter 3 built the cores; this chapter feeds them. Kernels touch memory
through loads and stores against a subdivided address space:
The two programmer-visible hazards
Two access patterns dominate GPU memory performance, and both come down to
how a warp’s 32 addresses relate to each other. For global memory, the
question is whether they fall in the same cache block —
warp lanes → addresses
memory transactions issued
Step to issue the first transaction/round.
For shared memory (one 32-bit bank per lane, one read + one write port
each), the question is whether two threads hit different rows of the same
bank — a
warp lanes → addresses (bank = word mod 8)
access rounds (conflicts → replay)
Step to issue the first transaction/round.
Programmers avoid both; the hardware tolerates both — that tolerance is the story of Fig 4.1.
4.1.1 One SRAM, two personalities
Fermi and Kepler implement shared memory and the L1 data cache as one configurable SRAM array: partly direct-mapped (shared), partly set-associative (cache) — early NVIDIA patents even call shared memory a “Global Register File,” and its latency is register-file-like. The surrounding machinery gives the instruction pipeline a non-stalling interface: hazards become replays, never stalls. Walk all four operation types through the numbered datapath:
step 0SHARED-MEMORY LOAD: the LSU sends one address per thread plus the operation type to the L1 block.
Details worth pinning down:
- Shared accesses bypass the tag unit (direct-mapped, constant latency), which is what lets the arbiter schedule the register-file writeback at accept time. The banks’ independent decoders are why arbitrary per-lane rows work at all.
- Global accesses are one cache block per cycle — 128-byte blocks
(Fermi/Kepler), split into four 32-byte
from Maxwell/Pascal on, matching the GDDR5 access atom. Less tag overhead, DRAM-shaped requests.sectors sector32-byte quarter of a 128-byte cache line, matching the GDDR5 access atom; Maxwell/Pascal L1s and L2 slices are sectored.Glossary → - The
is the GPU’s take on the classicpending request table pending request table (PRT)The GPU L1's MSHR-like structure: merges misses to the same block and remembers which deferred access to replay when the fill returns.Glossary → : merge same-block misses, remember which deferred access to replay, find it again via the request’s subid when the fill returns — and the fill unit locks the line so the replayed load cannot miss twice.MSHR MSHRMiss-status holding register: tracks an outstanding cache miss so further misses to the same line merge instead of replaying to memory.Glossary → - The L1 is
. CPUs avoid VIVT because context switches force flushes — but every warp on a GPU belongs to the same application, so the GPU takes the faster, simpler option (keeping page-based virtual memory for allocation simplicity and fragmentation control).virtually indexed and virtually tagged virtually-tagged L1GPU L1s are virtually indexed AND tagged (unlike CPU VIPT): no per-cycle translation needed, acceptable because all warps share one address space.Glossary → - Writes match their space’s locality: global stores → write-through, no-allocate (kernels stream results out and exit); local-memory spills → write-back, write-allocate (they’ll be re-read). Store data stages in the write data buffer; fully-covering coalesced writes may bypass the cache entirely (invalidating stale tags on the way).
- There is no L1 coherence. SM 1 can happily read a stale copy of a location SM 2 just wrote. NVIDIA’s Kepler-era answer: only spills, stack data, and read-only global data may live in L1. (Research on coherent GPU L1s and properly defined GPU memory consistency models is ongoing — the book cites Singh et al., Ren & Lis, Alglave et al.)
Check yourself
1. Predict the transactions (use the coalescing widget): 8 threads access addresses 0,4,8,…,28 (consecutive words). With 128-byte blocks, how many memory requests leave the core?
2. How does the unified L1 handle a shared-memory bank conflict WITHOUT stalling the pipeline?
3. Why can a GPU L1 be virtually indexed AND virtually tagged when CPU L1s usually aren't?
4. A load misses, and moments later a second load wants the SAME block. What does the PRT do?
5. Why write-through with NO write-allocate for global-memory stores?