Bufferization preserves tensor versions
Convert value semantics to storage while respecting aliases, old reads, ownership, and asynchronous users.
On this page
The question for today
What you’ll understand
- Explain why a new tensor value cannot always overwrite its input buffer.
- Identify a read-after-write conflict introduced by aliasing.
- Count live allocations and defer reclamation until every user retires.
Tensor IR can describe several logical versions without saying exactly where each is stored. Bufferization chooses concrete memory and sometimes reuses storage when the older value is no longer needed. That reuse is legal only if all observable reads still see the right version. A saved allocation is not a successful optimization when it silently changes an input that another consumer still uses. Track aliasing and lifetime before celebrating in-place execution.
A value update is not automatically a memory mutation
A functional tensor operation produces a result value while earlier tensor values retain their defined contents. Lowering it to a buffer write can reuse the input only if that mutation does not change a later required read of the old value. MLIR's One-Shot Bufferize analyzes operations and builds alias/equivalence information to make such decisions. Unsupported operations or incomplete effect information need conservative handling rather than a guess that an input has only one meaningful user.
A read-after-write conflict can appear when a proposed in-place result aliases an older tensor version. It is the newly introduced memory behavior that matters, not merely source-level variable names. Views can share allocations while covering different or overlapping ranges, so separate tensor handles do not imply separate storage. A compiler may insert a copy or choose a different destination to preserve old reads. Whether that copy can later be removed is another proof obligation.
Count allocations, not aliases
A view that aliases an allocation usually does not own a second payload of the same size. Memory accounting should therefore count unique live storage and separately include metadata, padding, and allocator overhead. Ownership determines who may release storage, while alias relationships identify users that still depend on it. A buffer cannot be deallocated safely just because the current block's last textual use has passed if an escaped alias or asynchronous operation remains active.
GPU launches and other asynchronous operations extend lifetime through completion, not merely submission. A host buffer passed to a device transfer may remain in use after the launching call returns. Reusing or freeing it early can create a race even if synchronous tests pass. Ownership-based deallocation infrastructure addresses specific IR contracts, but a pipeline must preserve those contracts through calls, regions, and lowering. Verify failure and exceptional paths as well as the normal return.
Inspect both values and resource lifetime
Test old-value consumers after a proposed overwrite, sliced aliases, returned buffers, and asynchronous completion. Compare tensor results before and after bufferization with a reference under the same numeric semantics. Separately inspect allocated bytes, copy volume, and deallocation placement. A test with one consumer can miss a conflict that appears only after graph branching, while a synchronous runtime can conceal a use-after-free that an asynchronous target exposes.
The cache lab contrasts residency with ownership. Reset and set both C=4, s=4, predict four misses and twelve hits among sixteen initial requests, then Step to add one hit. Its fully associative empty-start LRU address trace caps at 4096 requests. It has no tensor versions, aliases, reference ownership, or asynchronous completion. Evicting an abstract address is not evidence that a real buffer has no live readers; explain the lifecycle information missing from this toy before applying any memory-saving analogy.
Work it through
An old input is still needed
Let x=[1,2,3], y=x+10, and z=x+y under immutable logical tensor semantics and exact integers. Compare a separate y buffer with an illegal overwrite of x.
The correct y is[11,12,13], while old x remains[1,2,3]. Their sum gives z=[12,14,16].
If y overwrites x and both names now refer to[11,12,13], the same lowered addition reads the new values twice and returns[22,24,26]. That changes the computation.
For 1024 four-byte elements, retaining separate x and y before producing z uses 8192 payload bytes, compared with 4096 for one reused allocation. That potential saving is illegal here; total peak including z and overhead requires separate lifetime accounting.
Buffer reuse must preserve logical versions. A lower byte count cannot justify overwriting an input that still has a required consumer.
The living notebook
Explore the model
Interactive lab · cache
Residency is not buffer ownership
Reset, set C=4, s=4;predict 12 hits in 16 requests, then Step adds one hit. This capped 4096-request LRU model has no tensor aliases, ownership, deallocation, or asynchronous users.
- 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 buffer is reusable only after its actual version and lifetime obligations are satisfied.
Pause & reason
Check your understanding
Your turn
Try it yourself
An eight-KiB allocation has three aliasing views and one unfinished asynchronous reader. How many payload KiB should those aliases count as, and may the allocation be freed after its last host-side textual use?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Separate unique storage size from the number of handles and from operation completion.
Compare with the solution
The aliases share eight KiB of payload, not twenty-four KiB, before any separate metadata or other storage. The allocation cannot be freed while the asynchronous reader still requires it. The lifetime must reach the documented retirement/completion condition, and escaped aliases may add further obligations. A host-side last-use position alone does not establish that condition.
Keep the idea
Take it with you
- Bufferization must preserve distinct logical tensor versions.
- Alias handles and live allocation payload are different accounting units.
- Asynchronous users extend ownership beyond submission and textual use.
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.