research28 min studyLesson 992 in Engineering

Overlap work only while its data remains valid

Construct a CPU, transfer, and GPU pipeline with explicit completion events, buffer lifetimes, and measured concurrency.

On this page

What you’ll understand

  • Separate asynchronous submission from completed work and guaranteed overlap.
  • Compute an ideal finite-batch pipeline time.
  • Specify safe ownership transitions for reused host and device buffers.

A CPU can prepare the next input while a GPU processes an earlier one, but correctness depends on which buffers each operation still owns. Returning from an asynchronous copy call is not permission to overwrite its source immediately. Likewise, launching a kernel does not make its output ready for a CPU consumer. Build a dependency timeline first, then introduce streams, completion events, and enough buffer slots to preserve that timeline. The goal is cooperative execution with proven data lifetimes, followed by measurement of whatever overlap the actual platform supports.

Make submission and completion different states

Track preparation, host-to-device copy, device computation, device-to-host copy, and consumption as distinct stages. In CUDA 12.8.1, operations submitted to one stream follow its ordering rules; work in different streams can require explicit dependencies and is not guaranteed to execute concurrently. Record an event after the operation whose completion transfers ownership. A CPU consumer waits for the relevant completion rather than assuming that later wall-clock time or a successful enqueue implies the result is available.

Keep source and destination storage alive while operations may access it. A host input may be reused after its transfer completes if no other operation reads it; a device input may need to survive through kernel completion. Output buffers have different lifetimes because a later copy or consumer may still read them. Use separate ownership states for each allocation. A single global ready flag rarely describes a multi-stage ring accurately, especially during cancellation, error handling, or variable-sized requests.

reuse⁡(b) is allowed only after max⁡o∈users⁡(b)tcomplete(o)\operatorname{reuse}(b)\ \text{is allowed only after}\ \max_{o\in\operatorname{users}(b)}t_{\rm complete}(o)
users(b) includes every outstanding operation that may read or write buffer b, including CPU consumers and asynchronous transfers. Completion must be established by the platform’s synchronization contract, not inferred from submission time.↔ Scroll wide equations horizontally.

Model overlap with resources and sufficient buffering

Pinned host memory and suitable device capabilities are important for CUDA host-transfer overlap, but an Async API name alone does not establish nonblocking behavior for every argument combination. Pageable memory can require staging or synchronization. Query supported engine capabilities and inspect the actual timeline. Independent streams create scheduling opportunities while copy engines, memory bandwidth, kernel resource use, and default-stream interactions can still serialize portions of the intended pipeline.

An ideal pipeline processes independent chunks on separate stage resources with enough buffers and no extra stalls. Its steady interval is set by the slowest stage, while the first chunk still traverses every stage. Buffer capacity must support the chosen overlap; two composite slots held until final output completion may be insufficient for a four-stage ideal. Derive lifetimes and maximum simultaneously live chunks instead of claiming that double buffering always attains the bottleneck rate.

TN=∑j=1stj+(N−1)max⁡jtjT_N=\sum_{j=1}^{s}t_j+(N-1)\max_j t_j
This ideal deterministic pipeline formula assumes N≥1 independent chunks, one separate noncontending resource per stage, identical stage times, enough buffering, and no extra launch or queueing costs. It describes completion of a finite batch, not an unconditional CUDA performance guarantee.↔ Scroll wide equations horizontally.

Preserve the cooperative advantage under real load

Choose chunk size using both transfer amortization and pipeline occupancy. Very small chunks increase scheduling and transfer overhead; very large chunks reduce opportunities for overlap and can increase latency. Bound the number of in-flight chunks so CPU preparation cannot fill all pinned memory while the GPU is delayed. Backpressure should reserve the buffers and metadata needed to finish already accepted work, including output consumption and cancellation cleanup.

Measure CPU preparation, copy activity, GPU execution, and consumer stalls on a shared timeline. Compare isolated kernel time with complete request latency and loaded throughput. Synchronize only at the dependency boundary required for correctness; synchronizing the entire device after every stage can destroy intended overlap. Conversely, removing synchronization without an ownership proof creates races rather than speedup. Reproduce output checks across repeated ring wraparound and error paths because buffer reuse faults often remain hidden in a single successful chunk.

A four-stage ideal with enough independent buffers

A fictional chunk uses CPU preparation 3 ms, host-to-device transfer 2 ms, GPU compute 5 ms, and return transfer 1 ms. Assume four independent stage resources, enough separate buffers, no contention, and no other costs. Compare four serial chunks with the ideal pipelined batch.

  1. One chunk traverses 3+2+5+1=11 ms of stages. Four fully serial chunks therefore take 4×11=44 ms.

  2. The slowest stage is GPU compute at 5 ms, giving the ideal pipeline interval. First-chunk latency remains 11 ms even though later chunks can overlap.

  3. The ideal four-chunk completion time is 11+(4−1)×5=26 ms, a batch speedup of 44/26≈1.69. The average 6.5 ms per completed chunk is not the first request’s latency.

The result

This result requires the stated resource and buffering assumptions. A real implementation must establish event dependencies and measure overlap rather than infer 26 ms from asynchronous API usage.

Explore the model

Interactive lab

Interactive lab · queue

Bound in-flight preparation when service slows

Reset, set Arrival rate λ to 4 and Service rate μ to 3. Predict fluid backlog 4 initially and 5 after two Steps at t=1 s. Reset, explicitly set λ=2 and μ=3, then take two Steps: predict backlog 3. This constant-rate fluid toy illustrates pressure on an in-flight limit; it does not implement CUDA streams, buffers, copy engines, or an actual latency distribution. Its M/M/1 readout has separate Poisson/exponential/stability assumptions.

Bound in-flight preparation when service slowsFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. 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 forCooperation needs bounded in-flight work as well as overlap opportunities.

Check your understanding

When may a device input buffer be reused safely?

Try it yourself

An ideal three-stage pipeline has times 2,4,3 ms on independent resources and enough buffers. Find the completion time for five chunks and compare with serial execution. What changes if an input buffer is overwritten before its queued transfer finishes?

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

Give me a hint

Use fill time plus four bottleneck intervals, then consider correctness separately from timing.

Compare with the solution

Fill time is 9 ms and bottleneck interval is 4 ms, so five chunks take 9+4×4=25 ms ideally, versus 5×9=45 ms serially. Premature overwrite creates a data-lifetime race; a shorter observed runtime under that race is not a valid optimization or evidence that the pipeline model was achieved.

Take it with you

  • Treat asynchronous submission and completion as separate events.
  • Derive each buffer’s lifetime and provision enough slots for the intended overlap.
  • Measure actual engine concurrency and apply bounded backpressure.

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.