cuda stream concurrency

**CUDA Streams and Asynchronous GPU Execution** are the **programming mechanisms that enable overlapping of multiple GPU operations — kernel execution, memory transfers, and host computation — through independent queues (streams) of work, extracting maximum hardware utilization by keeping all GPU subsystems (compute, copy engines, host CPU) busy simultaneously rather than executing operations one-after-another**. **The Default (Synchronous) Problem** Without streams, GPU operations execute sequentially: copy H→D, kernel launch, copy D→H, repeat. The GPU compute units are idle during transfers, and the copy engines are idle during kernel execution. For a kernel taking 5 ms and transfers taking 2 ms each, utilization is only 5/(5+2+2) = 56%. **Stream Semantics** - A **stream** is an in-order queue of GPU operations. Operations within the same stream execute sequentially. - Operations in **different streams** may execute concurrently if hardware resources are available. - The **default stream** (stream 0) synchronizes with all other streams (legacy behavior) or is per-thread independent (per-thread default stream). **Overlap Patterns** **Double Buffering (Ping-Pong)**: ``` Stream A: [Copy H→D chunk 0] [Kernel chunk 0] [Copy D→H chunk 0] Stream B: [Copy H→D chunk 1] [Kernel chunk 1] [Copy D→H chunk 1] ``` While the kernel processes chunk 0, the copy engine simultaneously transfers chunk 1 to the device. Total time approaches max(compute, transfer) instead of compute + transfer. **Multi-Stream Pipeline**: With N streams and N data chunks, all pipeline stages run simultaneously. The steady-state throughput is limited by the slowest stage. **Hardware Requirements** - **Separate Copy Engines**: Modern GPUs have 2-3 independent copy engines (H→D, D→H, D→D / P2P). Bidirectional transfers overlap with each other AND with kernel execution. - **Concurrent Kernels**: GPUs can execute multiple small kernels simultaneously on different SMs when a single kernel doesn't saturate all SMs. Up to 16-128 concurrent kernels depending on architecture. - **Hyper-Q (MPS)**: Multiple CPU processes or threads can submit to independent hardware queues, enabling fine-grained concurrent kernel execution without false dependencies. **Synchronization Primitives** - **cudaStreamSynchronize(stream)**: Host blocks until all operations in the stream complete. - **cudaEventRecord / cudaStreamWaitEvent**: Fine-grained inter-stream dependencies. Stream B can wait for a specific event recorded in Stream A without synchronizing with the host. - **cudaEventElapsedTime**: Measure GPU-side elapsed time between two events for accurate kernel timing. **Common Pitfalls** - **Implicit Synchronization**: Some CUDA API calls (cudaMalloc, cudaMemcpy without Async) implicitly synchronize the device, serializing all streams. Use Async variants exclusively in multi-stream code. - **Page-Locked Memory**: Async transfers require pinned (page-locked) host memory. Pageable memory forces synchronous copies. CUDA Streams are **the concurrency abstraction that converts GPU programming from sequential batch processing into pipelined, overlapped execution** — extracting the last 20-40% of hardware utilization that separates a well-optimized GPU application from a naive one.

Go deeper with CFSGPT

Get AI-powered deep-dives, save terms, and run advanced simulations — free account.

Create Free Account