cuda::barrier / async copies#

cuda::barrier / async copies (sim only) The sim copies synchronously and has no memory pipeline, so an async copy is a plain memcpy and a barrier is the block barrier. This models the RESULT of the <cuda/barrier> + cooperative_groups::memcpy_async idiom, not its latency hiding.

Defined in code/simulator.h.

This page documents 7 symbols: 1 enums, 6 functions.

Enums#

Signature

Description

Availability

Location

Example

enum thread_scope

sim only

simulator.h:3593

Functions#

Signature

Description

Availability

Location

Example

arrival_token arrive(std::ptrdiff_t = 1)

sim only

simulator.h:3598

View

void arrive_and_drop()

sim only

simulator.h:3601

void arrive_and_wait()

sim only

simulator.h:3600

View

inline void init(barrier<Scope>* , std::ptrdiff_t )

sim only

simulator.h:3603

View

inline void memcpy_async(void* dst, const void* src, size_t n, B& )

sim only

simulator.h:3604

View

void wait(arrival_token&&) const

sim only

simulator.h:3599

View

Examples#

Code from the repository’s example corpus (code\*.cu); the highlighted line is the call site. These blocks are what the View links above open.

arrive (test_web_cs_awbarrier.cu:72)
62    SHARED_EXTERN(double, tmp);        // [SIM] was: extern __shared__ double tmp[];
63
64#pragma unroll
65    for (int offset = tile32.size() / 2; offset > 0; offset /= 2) {
66        threadSum += tile32.shfl_down(threadSum, offset);
67    }
68    if (tile32.thread_rank() == 0) {
69        tmp[tile32.meta_group_rank()] = threadSum;
70    }
71
72    auto token = barrier.arrive();
73
74    barrier.wait(std::move(token));
75
76    // The warp 0 will perform last round of reduction
77    if (tile32.meta_group_rank() == 0) {
78        double beta = tile32.thread_rank() < tile32.meta_group_size()
79                          ? tmp[tile32.thread_rank()]
80                          : 0.0;
81
82#pragma unroll
83        for (int offset = tile32.size() / 2; offset > 0; offset /= 2) {
arrive_and_wait (test_web_cs_globaltoshmem.cu:123)
113            float4* const       A4s = reinterpret_cast<float4*>(&As[threadIdx.y][t4x]);
114            float4* const       B4s = reinterpret_cast<float4*>(&Bs[threadIdx.y][t4x]);
115            const float4* const A4  = reinterpret_cast<const float4*>(&A[a + wA * threadIdx.y + t4x]);
116            const float4* const B4  = reinterpret_cast<const float4*>(&B[a + wA * threadIdx.y + t4x]);
117
118            cuda::memcpy_async(A4s, A4, sizeof(float4), bar);
119            cuda::memcpy_async(B4s, B4, sizeof(float4), bar);
120        }
121
122        // Synchronize to make sure the matrices are loaded
123        bar.arrive_and_wait();
124
125#pragma unroll
126        for (int k = 0; k < BLOCK_SIZE; ++k) {
127            Csub += As[threadIdx.y][k] * Bs[k][threadIdx.x];
128        }
129
130        // Synchronize before the next iteration overwrites the tiles
131        bar.arrive_and_wait();
132    }
133
134    int c                                 = wB * BLOCK_SIZE * blockIdx.y + BLOCK_SIZE * blockIdx.x;
init (test_web_cs_awbarrier.cu:108)
 98                                             double* partialResults, int size) {
 99#if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 700
100    cg::thread_block cta  = cg::this_thread_block();
101    cg::grid_group   grid = cg::this_grid();
102
103    cg::thread_block_tile<32> tile32 = cg::tiled_partition<32>(cta);
104
105    __shared__ cuda::barrier<cuda::thread_scope_block> barrier;
106
107    if (threadIdx.x == 0) {
108        init(&barrier, blockDim.x);
109    }
110
111    cg::sync(cta);
112
113    double threadSum = 0.0;
114    for (int i = grid.thread_rank(); i < size; i += grid.size()) {
115        threadSum += (double)(vecA[i] * vecB[i]);
116    }
117
118    // Each thread block performs reduction of partial dotProducts and writes to
119    // global mem.
memcpy_async (test_web_cs_globaltoshmem.cu:118)
108    const int t4x = threadIdx.x * 4;
109
110    for (int a = aBegin, b = bBegin; a <= aEnd; a += aStep, b += bStep) {
111        // Now, one fourth of the threads load four elements of each matrix
112        if (t4x < BLOCK_SIZE) {
113            float4* const       A4s = reinterpret_cast<float4*>(&As[threadIdx.y][t4x]);
114            float4* const       B4s = reinterpret_cast<float4*>(&Bs[threadIdx.y][t4x]);
115            const float4* const A4  = reinterpret_cast<const float4*>(&A[a + wA * threadIdx.y + t4x]);
116            const float4* const B4  = reinterpret_cast<const float4*>(&B[a + wA * threadIdx.y + t4x]);
117
118            cuda::memcpy_async(A4s, A4, sizeof(float4), bar);
119            cuda::memcpy_async(B4s, B4, sizeof(float4), bar);
120        }
121
122        // Synchronize to make sure the matrices are loaded
123        bar.arrive_and_wait();
124
125#pragma unroll
126        for (int k = 0; k < BLOCK_SIZE; ++k) {
127            Csub += As[threadIdx.y][k] * Bs[k][threadIdx.x];
128        }
wait (test_web_cs_awbarrier.cu:74)
64#pragma unroll
65    for (int offset = tile32.size() / 2; offset > 0; offset /= 2) {
66        threadSum += tile32.shfl_down(threadSum, offset);
67    }
68    if (tile32.thread_rank() == 0) {
69        tmp[tile32.meta_group_rank()] = threadSum;
70    }
71
72    auto token = barrier.arrive();
73
74    barrier.wait(std::move(token));
75
76    // The warp 0 will perform last round of reduction
77    if (tile32.meta_group_rank() == 0) {
78        double beta = tile32.thread_rank() < tile32.meta_group_size()
79                          ? tmp[tile32.thread_rank()]
80                          : 0.0;
81
82#pragma unroll
83        for (int offset = tile32.size() / 2; offset > 0; offset /= 2) {
84            beta += tile32.shfl_down(beta, offset);
85        }