Save memory traffic while retaining dense arithmetic
Separate dense matrix work, materialized intermediates, on-chip tiling, and the scope of I/O asymptotics.
On this page
The question for today
What you’ll understand
- Count dense attention matrix-multiply work independently of storage.
- Explain how online summaries avoid full score/probability matrices.
- State the memory model and limits of a FlashAttention I/O bound.
Exact tiled attention visits the same allowed query-key pairs as its materialized counterpart. Its speed comes from arranging where intermediate results live and how long loaded data are reused. A score tile can be formed in fast memory, normalized into a running row summary, multiplied by values, and discarded without writing a full score or probability matrix to device memory. This changes data movement and saved state dramatically. It does not by itself make dense attention linear in sequence length or eliminate the arithmetic required to compare every query with every key.
Count the operator before choosing the schedule
For one noncausal self-attention head with N tokens and equal query, key, and value width d, multiplying Q by K transpose produces N² scores. Multiplying the resulting probability matrix by V has the same leading matrix-multiply cost. Under the conventional count of two FLOPs per multiply-add, the two products total about four N²d FLOPs, excluding softmax, masking, and projections. Tiling changes their execution order rather than removing those pairs.
Materializing both score and probability matrices stores two N-by-N arrays if they are kept separately. In-place reuse can reduce that constant, but one quadratic intermediate remains. Online tiled execution instead keeps row statistics and output accumulators plus bounded working tiles. Its saved forward state can grow linearly with N for fixed d, even though the dense pair count remains quadratic. Report the exact memory boundary, including inputs and outputs, instead of calling every byte in the program auxiliary attention memory.
Tile to reuse the fast memory
A tile schedule loads blocks of Q, K, and V into the device’s faster local storage, computes scores, updates online summaries, and reuses values before eviction. The fast-memory capacity constrains tile shapes, output accumulators, and temporary fragments. Bigger tiles can improve reuse but consume registers or shared memory, reducing concurrent resident work. Consequently, choosing the largest legal tile is not automatically the fastest schedule on a real accelerator.
The original FlashAttention paper analyzes a two-level memory model with SRAM capacity M measured in scalar elements and HBM transfers counted in elements. Its dense algorithm has the stated asymptotic access count within the specified capacity range. That model is not a literal measurement of cache misses, transaction sizes, synchronization overhead, or every later kernel variant. It explains why reuse matters; actual latency still requires architecture- and shape-specific measurement.
An implementation can improve the same asymptotics
FlashAttention-2 improves work partitioning, reduces non-matmul operations, and changes how warps share work, while preserving the dense operator. These changes can improve utilization without altering the leading quadratic pair arithmetic. An asymptotic analysis would miss a speedup caused by less synchronization or better distribution of short-sequence work. Conversely, removing a quadratic materialization does not guarantee a speedup for tiny shapes whose overheads dominate.
When comparing kernels, distinguish logical bytes saved from measured memory traffic and actual runtime. The same tile may reread input blocks several times while still avoiding expensive full intermediate writes. Also distinguish prefill from incremental decoding: a single query attending to a long key cache has a rectangular score matrix and a different reuse problem from N-by-N training attention. Use the appropriate pair count and shape when reporting effective throughput.
Work it through
Quadratic arrays disappear while pair work remains
For a single dense noncausal head with N=4 and d=2, use float32 score/probability storage and float32 saved row log-sum-exp. Compare the two materialized intermediates with saved row statistics and count conventional leading matrix-multiply FLOPs.
Each N-by-N matrix has 16 scalars or 64 bytes. Keeping separate S and P arrays therefore uses 32 scalars, or 128 bytes, before counting Q, K, V, output, and other temporary storage.
A saved log-sum-exp has one scalar per row: 4 scalars or 16 bytes. A 2-by-2 working score tile is another 4 scalars or 16 bytes while it is live; that tile-size example is not a complete peak-memory accounting.
The two dense products still cost approximately 4×4²×2=128 FLOPs under the stated multiply-add convention. All 16 query-key pairs contribute; replacing quadratic saved arrays with row statistics did not remove their arithmetic.
The comparison isolates 128 bytes of separate materialized S/P payload versus 16 bytes of saved row normalization state, while the leading dense product count stays 128 FLOPs. It is not a complete runtime or peak-memory prediction.
The living notebook
Explore the model
Interactive lab · cache
Reuse depends on whether a working set fits
Reset, set Cache capacity C to 4 and Request stride s to 4. Predict 4 misses and 12 hits over the initial 16 requests, then 13 hits after Step. Reset, set C to 2 and s to 4; predict 16 initial misses and 17 after Step. Requests cap at 4096. This fixed LRU trace illustrates reuse capacity, not GPU shared-memory tiling or FlashAttention traffic.
- Hits / requests
- 0 / 16
- Hit rate
- 0%
- Address-stream period
- 16 addresses
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 forA useful reuse pattern can fail when its working set exceeds the available storage.
Pause & reason
Check your understanding
Your turn
Try it yourself
Repeat the payload and leading-FLOP counts for N=8, d=2, and four bytes per scalar. Count separate S/P arrays and one saved LSE per row only.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Quadratic arrays scale as N² while row statistics scale as N.
Compare with the solution
Each materialized matrix holds 64 scalars or 256 bytes; separate S and P total 512 bytes. Saved row LSE holds 8 scalars or 32 bytes. Leading matrix-multiply work is approximately 4×8²×2=512 FLOPs. Doubling N from four to eight quadruples these dense FLOPs and separate-array payloads but only doubles the row-statistic payload; other live tensors remain outside this isolated count.
Keep the idea
Take it with you
- Exact tiling preserves dense pair arithmetic.
- Avoided materialization and improved reuse reduce data movement.
- State the fast-memory model before interpreting an I/O bound.
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.