Promote data within a complete resource budget
Stage reused values only when memory-space semantics, synchronization, and occupancy constraints remain valid.
On this page
The question for today
What you’ll understand
- Separate logical memory spaces from guaranteed physical register placement.
- Count simultaneously live tiles and pipeline buffers.
- Explain synchronization and resource limits that constrain promotion.
Promotion moves frequently reused data into a memory space with a different scope or access cost, such as workgroup-shared storage. It can reduce transfers at one boundary while introducing copies, synchronization, and resource pressure elsewhere. A compiler needs both a legal data-lifetime plan and a target-aware capacity plan. Naming an allocation private or shared does not make its payload free, nor does a nominal fit guarantee the best performance.
Memory spaces define access and lifetime obligations
A global buffer can be accessed across a wider execution scope, while workgroup storage is shared within a defined block or workgroup. Private storage belongs to a smaller scope, but an IR memory-space label does not universally guarantee a hardware register for every value. Register allocation, spills, address-taking, and backend lowering affect the physical implementation. Use the actual target and generated resource report before claiming that all promoted values stay on chip or avoid memory traffic.
Copies into shared storage need a correct producer-consumer schedule. Threads must not read before the relevant copy completes, and storage must not be overwritten while earlier readers still use it. Barriers, asynchronous-copy waits, and memory visibility rules depend on the target and selected operations. Every participant required by a barrier must reach it under the allowed control flow. A pipeline that overlaps copies and arithmetic must preserve those stage lifetimes rather than merely adding a second buffer.
A faster space can reduce concurrent work
Larger tiles and more buffering increase live storage per workgroup. A capacity limit then restricts how many workgroups can reside together, even if each individual launch is valid. Threads, registers, scheduling granularity, and architectural limits can restrict concurrency further. Dividing total shared capacity by per-block bytes supplies only one upper bound. It is not a prediction of achieved occupancy or an argument that maximizing that number minimizes kernel time.
A promotion can also move the bottleneck. Reduced global traffic may expose arithmetic, synchronization, bank conflicts, or instruction overhead. An output already reused in cache can save less main-memory traffic than its logical size suggests. Compare actual boundary traffic and completion time under the same workload and numerical contract. If promotion adds a layout conversion, count its storage and execution too. Keep scalar and boundary cases in the correctness suite because incomplete tiles often have different synchronization paths.
Measure generated resources after checking values
Inspect shared/workgroup allocation, registers, spills, and synchronization after lowering, not only high-level tensor shapes. Test multiple pipeline depths and tile dimensions under target limits, retaining a correct fallback when a configuration is unsupported. Compare cold setup and steady execution if promotion requires initialization. Use race and memory tools where supported, and differential value checks for awkward tails. A benchmark that never exercises competing workgroups may hide the concurrency penalty of a resource-heavy schedule.
The Roofline lab is a synthetic boundary calculation. Reset and set both I=4, B=80, predict 320 GFLOP/s. Reset and re-set I=8, B=80 to predict 640 under the fixed 1000 GFLOP/s compute roof, then Play or Step. It does not allocate shared memory, synchronize copies, or model occupancy. Interpret the higher intensity only as a hypothetical reduction in bytes at the named boundary with fixed work, and identify the additional target resource evidence needed before expecting that ceiling to be approached.
Work it through
Double-buffered workgroup tiles
A hypothetical target permits 48 KiB workgroup storage per resident scheduling unit. One block retains two 32×32 four-byte input tiles in two buffering stages, plus a 32×32 four-byte scratch tile in the same memory space. Ignore allocation rounding and other limits.
Each 32×32 tile uses 4096 bytes, or 4 KiB. Two input families times two stages require 16 KiB, and the scratch tile adds 4 KiB, totaling 20 KiB per block.
This memory resource alone permits at most floor(48/20)=2 resident blocks. Registers, threads, and hardware limits can reduce that number.
Scaling every tile side to 64 quadruples these payloads to 80 KiB per block, exceeding the declared 48 KiB budget even for one block. A larger tile therefore needs a different storage plan or target rather than an optimistic performance assumption.
Count every live stage and scratch allocation. Resource-bound arithmetic constrains valid configurations before performance tuning begins.
The living notebook
Explore the model
Interactive lab · roofline
Traffic benefit needs a second resource check
Reset, set I=4, B=80, predict 320 GFLOP/s. Reset and re-set I=8, B=80, predict 640 under fixed 1000 compute roof. The synthetic model has no shared-memory allocation, spills, barriers, or occupancy.
- Attainable ceiling
- 640 GFLOP/s
- Ridge intensity
- 12.5 FLOP/byte
- Ceiling regime
- Memory-bound ceiling
Synthetic roofline ceiling min(1000, B·I), in GFLOP/s, with B in decimal GB/s and I in FLOP/byte. Playback traces the roof without changing the selected kernel. This upper-bound model is not a measured throughput prediction, hardware comparison or price model. 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 forPromotion can raise a traffic ceiling while lowering concurrency or increasing synchronization cost.
Pause & reason
Check your understanding
Your turn
Try it yourself
A target has 64 KiB of the selected shared resource. Each block uses two 12 KiB input buffers and 8 KiB scratch. Find the per-block payload and memory-only residency bound, then state one missing constraint.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Sum live buffers before dividing the target budget.
Compare with the solution
Per-block payload is 12+12+8=32 KiB, so this resource permits at most floor(64/32)=2 blocks. Register use, thread count, allocation granularity, or architectural block limits may reduce residency. Synchronization legality and actual traffic savings still need separate checks; a memory-only bound does not prove either correctness or a faster kernel.
Keep the idea
Take it with you
- Memory-space promotion introduces copy, synchronization, and lifetime obligations.
- Count all live pipeline stages and scratch in the same resource budget.
- A nominal fit or memory-only occupancy bound does not predict performance.
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.