.. _libcudacxx-extended-api-synchronization-pipeline: cuda::pipeline ================== .. toctree:: :hidden: :maxdepth: 1 pipeline/role pipeline/shared_state pipeline/destructor pipeline/make_pipeline pipeline/quit pipeline/consumer_release pipeline/consumer_wait pipeline/consumer_wait_prior pipeline/pipeline_producer_commit pipeline/producer_acquire pipeline/producer_commit Defined in header ````: .. code:: cuda template class cuda::pipeline { public: pipeline() = delete; __host__ __device__ ~pipeline(); pipeline& operator=(pipeline const&) = delete; __host__ __device__ void producer_acquire(); __host__ __device__ void producer_commit(); __host__ __device__ void consumer_wait(); template __host__ __device__ bool consumer_wait_for(cuda::std::chrono::duration const& duration); template __host__ __device__ bool consumer_wait_until(cuda::std::chrono::time_point const& time_point); __host__ __device__ void consumer_release(); __host__ __device__ bool quit(); }; The class template ``cuda::pipeline`` provides a coordination mechanism which can sequence :ref:`asynchronous operations `, such as :ref:`cuda::memcpy_async `, into stages. A thread interacts with a *pipeline stage* using the following pattern: 1. Acquire the pipeline stage. 2. Commit some operations to the stage. 3. Wait for the previously committed operations to complete. 4. Release the pipeline stage. For :ref:`cuda::thread_scope ` ``s`` other than ``cuda::thread_scope_thread``, a :ref:`cuda::pipeline_shared_state ` is required to coordinate the participating threads. *Pipelines* can be either *unified* or *partitioned*. In a *unified pipeline*, all the participating threads are both producers and consumers. In a *partitioned pipeline*, each participating thread is either a producer or a consumer. .. rubric:: Template Parameters .. list-table:: :widths: 25 75 :header-rows: 0 * - ``Scope`` - The scope of threads participating in the *pipeline*. .. rubric:: Member Functions .. list-table:: :widths: 25 75 :header-rows: 1 * - Member function - Description * - (constructor) [deleted] - ``cuda::pipeline`` is not constructible. * - ``operator=`` [deleted] - ``cuda::pipeline`` is not assignable. * - :ref:`(destructor) ` - Destroys the ``cuda::pipeline``. * - :ref:`producer_acquire ` - Blocks the current thread until the next *pipeline stage* is available. * - :ref:`producer_commit ` - Commits operations previously issued by the current thread to the current *pipeline stage*. * - :ref:`consumer_wait ` - Blocks the current thread until all operations committed to the current *pipeline stage* complete. * - :ref:`consumer_wait_for ` - Blocks the current thread until all operations committed to the current *pipeline stage* complete or after the specified timeout duration. * - :ref:`consumer_wait_until ` - Blocks the current thread until all operations committed to the current *pipeline stage* complete or until specified time point has been reached. * - :ref:`consumer_release ` - Release the current *pipeline stage*. * - :ref:`quit ` - Quits current thread's participation in the *pipeline*. .. note:: - A thread role cannot change during the lifetime of the pipeline object. .. rubric:: Example .. code:: cuda #include #include // Disables `pipeline_shared_state` initialization warning. #pragma nv_diag_suppress static_var_with_dynamic_init template __device__ void compute(T* ptr); template __global__ void example_kernel(T* global0, T* global1, cuda::std::size_t subset_count) { extern __shared__ T s[]; auto group = cooperative_groups::this_thread_block(); T* shared[2] = { s, s + 2 * group.size() }; // Create a pipeline. constexpr auto scope = cuda::thread_scope_block; constexpr auto stages_count = 2; __shared__ cuda::pipeline_shared_state shared_state; auto pipeline = cuda::make_pipeline(group, &shared_state); // Prime the pipeline. pipeline.producer_acquire(); cuda::memcpy_async(group, shared[0], &global0[0], sizeof(T) * group.size(), pipeline); cuda::memcpy_async(group, shared[0] + group.size(), &global1[0], sizeof(T) * group.size(), pipeline); pipeline.producer_commit(); // Pipelined copy/compute. for (cuda::std::size_t subset = 1; subset < subset_count; ++subset) { pipeline.producer_acquire(); cuda::memcpy_async(group, shared[subset % 2], &global0[subset * group.size()], sizeof(T) * group.size(), pipeline); cuda::memcpy_async(group, shared[subset % 2] + group.size(), &global1[subset * group.size()], sizeof(T) * group.size(), pipeline); pipeline.producer_commit(); pipeline.consumer_wait(); compute(shared[(subset - 1) % 2]); pipeline.consumer_release(); } // Drain the pipeline. pipeline.consumer_wait(); compute(shared[(subset_count - 1) % 2]); pipeline.consumer_release(); } template void __global__ example_kernel(int*, int*, cuda::std::size_t); `See it on Godbolt `_