advanced27 min studyLesson 518 in Engineering

Measure the boundary instead of declaring every graph break a failure

Account for compilation, eager regions, dispatch, synchronization, and fusion limits using a fictional pipeline and a synthetic roofline ceiling.

On this page

What you’ll understand

  • Explain the correctness and performance roles of eager fallback boundaries.
  • Calculate a complete cold-to-warm execution budget.
  • Distinguish measured boundary cost from a memory-throughput upper bound.

A graph break marks a boundary in captured execution, and its consequence depends on the surrounding work. It can prevent profitable fusion or introduce dispatch and synchronization, yet it can also preserve a small host interaction outside a large efficiently compiled region. Removing a break by changing semantics is not a performance improvement. The useful engineering question is which correct arrangement minimizes the relevant workload's cost, including capture, compilation, artifact reuse, eager work, and the conditions under which measurements were completed.

Locate both the cause and the actual boundary work

In PyTorch 2.9's documented partial-capture model, unsupported operations or data-dependent host behavior can lead to eager execution between captured regions. A value inspection that requires a device result on the host can also expose synchronization cost, though a graph break does not universally imply a device synchronization. Capture options and supported operations are version-sensitive. Inspect diagnostics and a profiler for the exact program instead of inferring cost solely from the number of graphs shown in a report.

Some boundaries are intentional. A request logger might be tiny relative to the matrix product before and after it, or an infrequently executed error path may not justify aggressive capture work. Conversely, a break inside a short operation repeated hundreds of times can dominate launch and dispatch costs. Count frequency as well as duration. Preserve equivalent input preparation, host behavior, and device completion when comparing alternatives; otherwise removing a log operation or failing to wait for work can look like a compiler speedup.

T(N)=C+N ⁣(Rtensor+Reager+Rboundary)T(N)=C+N\!\left(R_{\rm tensor}+R_{\rm eager}+R_{\rm boundary}\right)
All terms are elapsed milliseconds for the same completed work, N is a positive integer call count, and C covers the compilation events assumed in the case. This additive fictional model excludes overlap and variation; actual profiling must establish whether such addition is appropriate.↔ Scroll wide equations horizontally.

Bigger capture does not guarantee better kernels

Combining regions may avoid materializing an intermediate or launching another kernel. It can also enlarge live ranges, increase register pressure, alter scheduling opportunities, or create a more expensive compilation. These effects depend on operation shapes and the backend. A fully captured graph is therefore useful evidence about representability, not a universal certificate of faster execution. Choose performance hypotheses with an identified mechanism, such as removing a repeated host round trip, then test that mechanism with controlled inputs.

For memory-sensitive operations, reduced traffic can raise a throughput ceiling without establishing the achieved rate. The roofline model divides operation count by bytes moved at a stated memory boundary; its bandwidth term is an upper bound under that model. Do not substitute allocation size for actual traffic or count a read only once when the implementation reloads it. Fusion can change both traffic and other bottlenecks, and a boundary change may affect dispatch without changing arithmetic intensity at all.

Pceiling=min⁡(Pmax⁡,BI),I=FDP_{\rm ceiling}=\min(P_{\max},BI),\qquad I=\frac{F}{D}
F is FLOP count and D bytes transferred at the declared boundary, so I is FLOP/byte. In the lab B is decimal GB/s and the synthetic compute ceiling is 1,000 GFLOP/s. This bound contains no launch, synchronization, compilation, or register-pressure timing model.↔ Scroll wide equations horizontally.

Separate cold, warm, and changing-contract measurements

Report the initial call and steady compatible calls separately, then add a workload that changes relevant guards. Include repetitions and a declared aggregation rule rather than selecting the fastest sample without context. For asynchronous accelerators, wait for the result at the chosen measurement boundary, as the JAX JIT documentation demonstrates. Also record what warm-up did: it may populate artifact caches, memory pools, and device libraries. Those effects are real parts of the experiment, not automatically costs of the same compiler stage.

In the roofline lab, Reset and set both I=8 FLOP/byte and B=80 GB/s. Predict the ceiling 640 GFLOP/s, then Play or Step to trace it. Reset and set both I=16,B=80 for the separate ceiling 1,000 GFLOP/s. These are hypothetical intensity choices rather than the measured effect of deleting a graph break. Playback only traces the selected roof. Use this instrument to distinguish a potential traffic benefit from a guaranteed runtime saving, then return to the actual program's synchronized measurements.

Include eager and boundary work in the break-even point

A fictional eager function takes 5 ms per call. A staged alternative costs 100 ms to compile, then spends 2.5 ms in compiled tensor work, 0.5 ms in retained eager work, and 0.5 ms in boundary overhead per call. Assume additive nonoverlapping completed timings and one artifact.

  1. Add the staged per-call terms: 2.5+0.5+0.5=3.5 ms. The complete staged budget is 100+3.5N ms, not just the 2.5N tensor term.

  2. Solve 100+3.5N<5N, giving N>100/1.5≈66.67. The first whole-number saving occurs at sixty-seven compatible calls.

  3. At one hundred calls, staged costs 450 ms and eager 500 ms, a fifty-millisecond modeled saving. If repeated compilation or a synchronization cost was omitted, this conclusion must be recalculated.

The result

This boundary-containing arrangement can still be profitable. The arithmetic neither proves every break harmless nor proves that capturing the retained eager region would improve the result.

Explore the model

Interactive lab

Interactive lab · roofline

Separate a traffic ceiling from a boundary timing measurement

Fresh Reset → set both I=8,B=80 predicts 640 GFLOP/s; Reset → set both I=16,B=80 predicts 1,000 GFLOP/s. Play or Step traces the fixed synthetic roof. No compiler, launch overhead, graph break, or synchronization is simulated.

Separate a traffic ceiling from a boundary timing measurementSynthetic 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. Current readings: Attainable ceiling: 640 GFLOP/s; Ridge intensity: 12.5 FLOP/byte; Ceiling regime: Memory-bound ceiling. All parameters are adjustable with the labeled controls below.Hypothetical roofline upper bound: 640 GFLOP per second at operational intensity 8 FLOP per byte and bandwidth 80 gigabytes per second.0.1110641101001000Operational intensity · FLOP/byte · log scaleCeiling · GFLOP/s · log scalePeak: 1000
Attainable ceiling / kernelBandwidth roof / traceCompute ceiling
Attainable ceiling
640 GFLOP/s
Ridge intensity
12.5 FLOP/byte
Ceiling regime
Memory-bound ceiling
t = 0 s

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 forA higher theoretical ceiling is a performance hypothesis that still needs equivalent completed-work measurements.

Check your understanding

A version of a model has fewer graph breaks but runs slower on the declared workload. Which interpretation is justified?

Try it yourself

Suppose a rewrite removes the 0.5 ms boundary term but raises compilation cost from 100 to 180 ms, while tensor and retained eager work stay at 3 ms total. Compare both staged alternatives over one hundred calls.

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

Give me a hint

The original staged total was 450 ms. Account for the larger one-time cost before crediting the per-call saving.

Compare with the solution

The rewrite costs 180+100×3=480 ms, thirty milliseconds more than the original 100+100×3.5=450 ms. It still beats the assumed 500 ms eager total by twenty milliseconds, but it is worse than the boundary-containing alternative at this call count. The rewrite's eighty-millisecond extra compilation needs more than 160 calls to recover through a half-millisecond saving per call; at 160 the alternatives tie.

Take it with you

  • Graph breaks can preserve useful eager behavior while creating workload-dependent costs.
  • Capture size and kernel performance are separate questions.
  • Compare complete synchronized budgets and keep throughput ceilings distinct from measurements.

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.