advanced26 min studyLesson 464 in Engineering

Device-cache reuse and bypass

Reason about working sets and cache operators without treating them as ordering primitives or universal performance switches.

On this page

What you’ll understand

  • Distinguish coalescing from temporal cache reuse.
  • Explain the scoped meaning of L1 and L2 cache hints.
  • Test a reuse hypothesis without assuming real GPU caches use toy LRU.

A tensor load can be perfectly coalesced yet repeatedly fetch data that is never reused. Another load can benefit from nearby warps revisiting the same sectors. Caching addresses reuse across accesses, while coalescing organizes one access’s addresses. This lesson follows CUDA 12.8.1 and PTX ISA 8.7 documentation, using Ampere-class global-load behavior as context while keeping cache sizes, replacement, and operator support target-specific.

Identify reuse distance and working set

A working set is the data needed over a useful execution interval. A tile reused many times may benefit from cache residency, while a streaming pass much larger than the cache can evict reusable data. Access order and concurrent blocks change the effective reuse distance. Record whether the same bytes are revisited before enough competing data arrives to displace them. A cache hit rate aggregated over a whole kernel can hide an important tensor that misses frequently or a high-rate stream with little performance impact.

Coalescing and reuse interact but remain different. Adjacent warps may reuse sectors over-fetched by a misaligned access, reducing external-memory traffic relative to a naive per-warp sum. Shared memory can provide explicit block-local reuse when the algorithm justifies its synchronization and capacity cost. Do not assume an L1 hit removes all latency or that an L2 hit has the same cost as a register access. Measure traffic and stalls at the level relevant to the optimization question.

Bmiss≈Nrequests(1−h)LB_{\mathrm{miss}}\approx N_{\mathrm{requests}}(1-h)L
For an illustrative equal-line model, h is hit fraction, L bytes per miss, and each miss fetches one line. The result is bytes. Real sectors, merged requests, write policies, and several cache levels can invalidate this simple traffic estimate.↔ Scroll wide equations horizontally.

A cache operator is not a memory-order proof

PTX load cache operators express documented cache behavior or hints, with support and implementation depending on the target. For example, load operator .ca requests caching at all levels, while .cg requests caching at the global level rather than L1; the documented distinction still retains L2. These PTX 8.7 operators are performance hints and do not change memory-consistency semantics. Do not describe a global-level cache operator as bypassing every cache or forcing every access to DRAM. Store policies and specialized access paths have separate semantics, so transferring one load rule to every instruction is unsafe.

Cache policy does not establish producer-consumer synchronization. A reader can still race with a writer even when a cache is bypassed, and a volatile qualifier is not a substitute for the required atomic ordering or synchronization scope. A performance hint cannot make stale or out-of-lifetime accesses correct. Check the memory model and completion dependencies first, then compare cache-policy variants on equivalent valid executions. Also record how cache configuration trades resources with shared memory on architectures where those capacities interact.

period⁡=16gcd⁡(16,s)\operatorname{period}=\frac{16}{\gcd(16,s)}
This formula belongs to the lab’s deterministic address stream (i times stride s) mod 16. It counts distinct toy addresses, not real GPU cache lines, sets, or address hashing.↔ Scroll wide equations horizontally.

Separate a reuse experiment from a benchmark

Warm and cold runs answer different questions. Control initialization, preceding kernels, input size, and measurement synchronization so that a claimed cache improvement is not simply a different starting state. Test whether the optimization survives other representative shapes and concurrent work. A policy that favors one persistent tensor can harm another. Cache-bypass experiments should therefore report the workload’s reuse hypothesis and measured consequences, rather than a universal rule to disable or enable a cache for all AI kernels.

The cache lab is an exact fully associative LRU toy, starting empty with sixteen requests already counted. Reset, set capacity to 4 and stride to 4, predict hits after seventeen requests, then Step once. Compare a fresh Reset with both capacity at 2 and stride at 4 before another Step. Each Step adds one request here. The four-address cycle fits the first cache but not the second. This instrument is not a GPU cache: it has no sectors, associativity conflicts, cache operators, or hardware replacement policy.

Check a toy working-set claim

Use the lab’s address stream (4i) mod 16 for seventeen requests from an empty fully associative LRU cache. Compare capacities four and two addresses. Do not interpret either as a real GPU cache configuration.

  1. The stream cycles through 0, 4, 8, and 12, so its working set is four distinct addresses. The first four requests are compulsory misses.

  2. At capacity four, all remaining thirteen requests hit, giving 13/17, approximately 76.47%.

  3. At capacity two, each address is evicted before its next appearance in the four-address cycle. All seventeen requests miss, so hit rate is zero.

The result

The toy exposes reuse relative to capacity. Actual device-cache conclusions require target-specific measurements and cannot be read directly from these counts.

Explore the model

Interactive lab

Interactive lab · cache

A known working set in a toy cache

Reset, set cache capacity C = 4 and request stride s = 4, predict hits at seventeen requests, then Step once. Compare a fresh Reset with both C = 2 and s = 4 before Step. The instrument is fully associative LRU, not a GPU cache or cache-operator benchmark.

A known working set in a toy cacheA fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Current readings: Hits / requests: 0 / 16; Hit rate: 0%; Address-stream period: 16 addresses. All parameters are adjustable with the labeled controls below.Fully associative LRU cache after 16 deterministic requests: 0 hits and 16 misses.Most recent 16 requestsaddress = i × 3 mod 160M3M6M9M12M15M2M5M8M11M14M1M4M7M10M13MCurrent cache order · oldest → newest471013Latest address 13 · miss: inserted as newestToy address stream · period 16 · starts empty
Cached addressMiss / evictionMost recent request
Hits / requests
0 / 16
Hit rate
0%
Address-stream period
16 addresses
t = 0 s

A fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forReuse depends on access order and capacity; real cache policies need separate architectural evidence.

Check your understanding

A PTX global-load cache policy reduces L1 use. Which claim does not follow merely from that choice?

Try it yourself

For a deliberately simple line model, 1,000 requests fetch 64 bytes on each miss. Compare modeled fetched bytes at hit fractions 0.75 and 0.5. Name one reason this calculation can differ from GPU external-memory traffic.

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Multiply only misses by bytes per miss and keep the model’s boundaries explicit.

Compare with the solution

The estimates are 1,000 × 0.25 × 64 = 16,000 bytes and 1,000 × 0.5 × 64 = 32,000 bytes. GPU sectoring, request merging, cache hierarchy, write traffic, and reuse outside the counted request stream can change external-memory traffic. The calculation supports a toy hypothesis, not a measured bandwidth or cache-policy claim.

Take it with you

  • Coalescing organizes one access; caching exploits reuse across accesses.
  • Cache hints have scoped semantics and do not establish memory ordering.
  • Toy LRU traces and real GPU-cache measurements answer different questions.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.