core24 min studyLesson 457 in Engineering

Events: connect streams without blocking the entire device

Trace record and wait placement, event timing boundaries, and safe buffer reuse.

On this page

What you’ll understand

  • Place an event after its producer and a wait before its consumer.
  • Distinguish a device-side stream wait from host event synchronization.
  • Interpret event timing as a defined interval rather than host submission latency.

An event can mark progress through a stream and let another stream depend on that progress. The useful relationship comes from where record and wait operations are placed, not from the event’s variable name. Events can also support timing when created and used appropriately, but timing a chosen stream interval is different from measuring CPU launch overhead or proving all device work completed. Keep dependency events and timing experiments conceptually separate.

Record the producer boundary, then wait at the consumer

Submit the producer in S1, record event E in S1 after it, and submit a wait for that recorded event in S2 before the consumer. Work in S2 after the wait cannot proceed past the required event completion until the captured producer boundary is reached. The event does not automatically include later work added after its record. Place the record too early and the consumer can race with the actual producer; place the wait after the consumer and it cannot retroactively fix the read.

cudaStreamWaitEvent creates a stream dependency without making the CPU wait for all device work. cudaEventSynchronize instead blocks the host until the event’s captured work is complete, and cudaEventQuery lets the host ask whether it is complete. A not-ready result is not a failure of the kernel by itself. Check API return values and create an acyclic dependency graph. An event that has never been recorded represents no captured work, so waiting on it does not wait for a future record. Do not use an unrecorded placeholder as a barrier.

P→record⁡(E)→wait⁡(E)→CP\to\operatorname{record}(E)\to\operatorname{wait}(E)\to C
P and C are producer and consumer operations; record is placed in the producer stream and wait before C in the consumer stream. The chain describes the intended captured dependency, not the order of CPU function return times.↔ Scroll wide equations horizontally.

Event reuse and buffer lifetime need a generation story

An event object can be recorded again, so a reusable pipeline must ensure each wait refers to the intended captured record according to the API’s most-recent-record semantics at submission. Give each buffer slot an explicit lifecycle: input available, producer complete, consumer complete, then reuse permitted. Reusing one event carelessly across multiple in-flight iterations can associate a wait with the wrong boundary. Separate event objects per pipeline slot or another proven protocol can make that lifecycle easier to reason about.

The completion that protects a buffer depends on its last relevant user. A producer-ready event allows a consumer to begin; it does not allow the host to overwrite the buffer while the consumer still reads it. Record or observe a consumer-complete boundary before reuse. The same principle applies to asynchronous copies and deallocation: launch order is not a lifetime proof unless the deallocation or overwrite is correctly ordered after every use under the actual API semantics.

TCstart≥max⁡(TPfinish,TS2prior finish)T_C^{\rm start}\geq\max(T_P^{\rm finish},T_{S2}^{\rm prior\ finish})
This ideal scheduling bound assumes the correctly placed event dependency and that the consumer also follows earlier S2 work. Times share one origin. Additional scheduling and resource delays can make the consumer start later.↔ Scroll wide equations horizontally.

Timing includes exactly the interval you bracket

For a simple timing experiment, record a start event and an end event around the intended work in a suitable stream and wait for completion before reading elapsed time. Timing-enabled events are required for elapsed-time queries. Other work, contention, and placement can influence what is measured, so do not equate an event interval with an isolated instruction cost. A CPU timer around cudaEventRecord calls measures a different interval unless it also accounts for device completion.

The network lab shows a fixed data-dependency graph, not asynchronous execution. Reset, set x=2 and w=1, predict sigmoid(1.5)≈0.818, then Step. The output mathematically depends on the earlier multiplication, but the graph has no streams, records, waits, or event generations. Use that limited graph to name the producer and consumer, then add the actual event edge in a separate schedule. Changing a number in the lab cannot validate a real buffer-lifetime protocol.

Overlap independent setup before a consumer

Producer P runs in S1 from 0 to 4 ms, followed by event E. S2 has independent setup from 0 to 2 ms, then waits for E before a 3 ms consumer C. Assume no resource contention or overhead.

  1. S2’s setup finishes at 2 ms, but P has not completed. The event wait holds C until the producer boundary at 4 ms, so the earliest C start is max(2,4)=4 ms.

  2. C then finishes at 4+3=7 ms. The host need not block during the two-millisecond wait interval if it submitted a stream wait rather than performing a broad host synchronization.

  3. Reusing P’s output buffer at 4 ms would be too early because C uses it until 7 ms. A separate completion boundary after C protects that reuse; E only established producer readiness.

The result

Correct placement permits useful overlap while preserving the consumer’s dependency. Ready-for-consumption and safe-for-reuse are different boundaries.

Explore the model

Interactive lab

Interactive lab · network

Name dependencies before scheduling them

Reset, set x=2 and w=1, predict σ(1.5)≈0.818, then Step. The fixed sigmoid graph shows a mathematical dependency only; it does not record events, wait on streams, time kernels, or validate buffer reuse.

Name dependencies before scheduling themOne inspectable sigmoid unit, σ(wx − 0.5). Playback traces the computation graph. There is no training, attention mechanism or hidden deep network. Current readings: Product · wx: 1.2; Logit · wx − 0.5: 0.7; Sigmoid output: 0.6682. All parameters are adjustable with the labeled controls below.One input. One weight. One sigmoid.x1.20× w1.20+ b0.70σ0.668output0.668w = 1.00b = −0.50σ(z) = 1 / (1 + exp(−z))
Computation graphSignal trace
Product · wx
1.2
Logit · wx − 0.5
0.7
Sigmoid output
0.6682
t = 0 s

One inspectable sigmoid unit, σ(wx − 0.5). Playback traces the computation graph. There is no training, attention mechanism or hidden deep network. 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 scheduling edge must be attached to the actual producer and last consumer, not just to a shared variable name.

Check your understanding

An event is recorded immediately before the producer kernel. S2 waits on it and then reads the producer’s output. What is wrong?

Try it yourself

A producer finishes at 6 ms. Earlier consumer-stream work finishes at 8 ms, and the dependent consumer takes 2 ms. Under the same ideal assumptions, when can it start, finish, and permit reuse of its input?

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

Give me a hint

Apply both the producer dependency and the consumer stream’s own earlier work.

Compare with the solution

It starts no earlier than max(6,8)=8 ms and finishes at 10 ms. Reuse protected by this consumer is safe only after the corresponding completion at or after 10 ms, assuming there are no other users and the required host/device visibility conditions are met.

Take it with you

  • Record and wait placement defines the actual captured dependency.
  • Host waits, device stream waits, queries, and timing serve different purposes.
  • Producer readiness does not imply a buffer’s last consumer has finished.

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.