Grid group (cooperative launch)#

this_grid().sync() is a GRID-WIDE barrier. It only means anything when every block is resident, which is what a cooperative launch guarantees — so use LAUNCH_COOP / LAUNCH_DYN_COOP (see below) for kernels that call it. Under an ordinary LAUNCH the sim runs one block at a time and can only degrade it to the block barrier (which is exact for a single-block grid).

Defined in code/simulator.h.

This page documents 35 symbols: 2 classes, 3 structs, 30 functions.

Classes#

Signature

Description

Availability

Location

Example

class coalesced_group : public thread_group

Coalesced group. A real coalesced_group is the set of *currently-converged* lanes of a warp; tracking that needs per-branch divergence state, which the one-fiber-at-a-time scheduler does not keep. On …

sim only

simulator.h:1270

class grid_group

this_grid().sync() is a GRID-WIDE barrier.

sim only

simulator.h:1233

Structs#

Signature

Description

Availability

Location

Example

struct greater

sim only

simulator.h:1252

View

struct less

sim only

simulator.h:1251

struct plus

cg::reduce (CUDA 11+) and its common ops.

sim only

simulator.h:1250

View

Functions#

Signature

Description

Availability

Location

Example

int all(int pred) const

sim only

simulator.h:1282

View

int any(int pred) const

sim only

simulator.h:1281

View

unsigned ballot(int pred) const

sim only

simulator.h:1283

View

inline coalesced_group binary_partition(const G&, bool )

sim only

simulator.h:1287

View

unsigned block_rank() const

sim only

simulator.h:1238

inline coalesced_group coalesced_threads()

sim only

simulator.h:1285

View

dim3 group_dim() const

sim only

simulator.h:1244

bool is_valid() const

sim only

simulator.h:1236

inline coalesced_group labeled_partition(const G&, L )

sim only

simulator.h:1288

View

unsigned meta_group_rank() const

sim only

simulator.h:1276

View

unsigned meta_group_size() const

sim only

simulator.h:1277

View

unsigned num_blocks() const

sim only

simulator.h:1237

unsigned num_threads() const

sim only

simulator.h:1241

unsigned num_threads() const

sim only

simulator.h:1275

inline T reduce(const thread_block_tile<N>& tile, T val, Op op)

sim only

simulator.h:1253

View

inline T reduce(const coalesced_group&, T val, Op)

reduce over a singleton coalesced group returns the thread’s own value.

sim only

simulator.h:1290

View

inline T reduce(const coalesced_group&, T val, plus<T>)

sim only

simulator.h:1291

View

T shfl (T v, unsigned ) const

sim only

simulator.h:1278

View

T shfl_down(T v, unsigned ) const

sim only

simulator.h:1280

View

T shfl_up (T v, unsigned ) const

sim only

simulator.h:1279

unsigned size() const

sim only

simulator.h:1242

View

unsigned size() const

sim only

simulator.h:1274

View

void sync() const

sim only

simulator.h:1235

View

inline void sync(const grid_group& g)

sim only

simulator.h:1247

View

inline void sync(const thread_block_tile<N>& t)

Free sync() overloads (real CG provides sync(g) for every group type).

sim only

simulator.h:1259

View

void sync() const

sim only

simulator.h:1272

View

inline void sync(const coalesced_group& g)

sim only

simulator.h:1286

View

inline grid_group this_grid()

sim only

simulator.h:1246

View

unsigned thread_rank() const

sim only

simulator.h:1243

View

unsigned thread_rank() const

sim only

simulator.h:1273

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.

greater (test_web_cs_warpaggr_multi.cu:85)
75        const int bucket = srcArr[i];
76        if (bucket < numOfBuckets) indicesBuckets[atomicAggIncMulti(bucket, bucketCounters)] = i;
77    }
78}
79
80// Warp-aggregated atomic max in a multi-bucket layout (verbatim).
81__device__ void atomicAggMaxMulti(const int bucket, int* counter, const int valueForMax) {
82    cg::coalesced_group active = cg::coalesced_threads();
83    auto labeledGroup = cg::labeled_partition(active, bucket);
84
85    const int maxValueInGroup = cg::reduce(labeledGroup, valueForMax, cg::greater<int>());
86    if (labeledGroup.thread_rank() == 0) atomicMax(&counter[bucket], maxValueInGroup);
87}
88
89__global__ void calculateMaxInEachBuckets(const int* srcArr, const int* valueInBuckets,
90                                          int* bucketsMax, const int srcSize,
91                                          const int numOfBuckets) {
92    cg::grid_group grid = cg::this_grid();
93
94    for (int i = (int)grid.thread_rank(); i < srcSize; i += (int)grid.size()) {
95        const int bucket = srcArr[i];
96        if (bucket < numOfBuckets) atomicAggMaxMulti(bucket, bucketsMax, valueInBuckets[i]);
plus (test_coop_groups.cu:73)
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
all (test_web_warp_primitives.cu:124)
114        if (v_down[t]      != e_down)    ok = false;
115        if (v_xor[t]       != e_xor)     ok = false;
116    }
117
118    std::printf("threadIdx: ");   for (int t=0;t<n;++t) std::printf("%2d ", t);           std::printf("\n");
119    std::printf("lane_id:   ");   for (int t=0;t<n;++t) std::printf("%2d ", lane[t]);     std::printf("\n");
120    std::printf("shfl(l2):  ");   for (int t=0;t<n;++t) std::printf("%2d ", v_shfl[t]);   std::printf("\n");
121    std::printf("shfl_up:   ");   for (int t=0;t<n;++t) std::printf("%2d ", v_up[t]);     std::printf("\n");
122    std::printf("shfl_down: ");   for (int t=0;t<n;++t) std::printf("%2d ", v_down[t]);   std::printf("\n");
123    std::printf("shfl_xor:  ");   for (int t=0;t<n;++t) std::printf("%2d ", v_xor[t]);    std::printf("\n");
124    std::printf("ballot(tid>0)=%x  ballot(tid==0)=%x  all(FULL)=%d  any(FULL)=%d\n",
125                ballot_pos[0], ballot_zero[0], all_full[0], any_full[0]);
126    std::printf("warp primitives (%u lanes, width %u): %s\n",
127                BLOCK_SIZE, WIDTH, ok ? "PASSED" : "FAILED");
128
129    CHECK(cudaFree(d_lane)); CHECK(cudaFree(d_all)); CHECK(cudaFree(d_any));
130    CHECK(cudaFree(d_shfl)); CHECK(cudaFree(d_up)); CHECK(cudaFree(d_down));
131    CHECK(cudaFree(d_xor)); CHECK(cudaFree(d_bpos)); CHECK(cudaFree(d_bzero));
132    return ok ? 0 : 1;
133}
any (test_web_cs_reduction_full.cu:111)
101    }
102
103    // write result for this block to global mem
104    if (cta.thread_rank() == 0)
105        g_odata[blockIdx.x] = mySum;
106}
107
108/*
109    This version is completely unrolled, unless warp shuffle is available, then
110    shuffle is used within a loop. It uses a template parameter to achieve
111    optimal code for any (power of 2) number of threads. (verbatim)
112*/
113template <class T, unsigned int blockSize> __global__ void reduce5(T *g_idata, T *g_odata, unsigned int n) {
114    // Handle to thread block group
115    cg::thread_block cta   = cg::this_thread_block();
116    T               *sdata = SharedMemory<T>();
117
118    // perform first level of reduction,
119    // reading from global memory, writing to shared memory
120    unsigned int tid = threadIdx.x;
121    unsigned int i   = blockIdx.x * (blockSize * 2) + threadIdx.x;
ballot (test_web_warp_primitives.cu:124)
114        if (v_down[t]      != e_down)    ok = false;
115        if (v_xor[t]       != e_xor)     ok = false;
116    }
117
118    std::printf("threadIdx: ");   for (int t=0;t<n;++t) std::printf("%2d ", t);           std::printf("\n");
119    std::printf("lane_id:   ");   for (int t=0;t<n;++t) std::printf("%2d ", lane[t]);     std::printf("\n");
120    std::printf("shfl(l2):  ");   for (int t=0;t<n;++t) std::printf("%2d ", v_shfl[t]);   std::printf("\n");
121    std::printf("shfl_up:   ");   for (int t=0;t<n;++t) std::printf("%2d ", v_up[t]);     std::printf("\n");
122    std::printf("shfl_down: ");   for (int t=0;t<n;++t) std::printf("%2d ", v_down[t]);   std::printf("\n");
123    std::printf("shfl_xor:  ");   for (int t=0;t<n;++t) std::printf("%2d ", v_xor[t]);    std::printf("\n");
124    std::printf("ballot(tid>0)=%x  ballot(tid==0)=%x  all(FULL)=%d  any(FULL)=%d\n",
125                ballot_pos[0], ballot_zero[0], all_full[0], any_full[0]);
126    std::printf("warp primitives (%u lanes, width %u): %s\n",
127                BLOCK_SIZE, WIDTH, ok ? "PASSED" : "FAILED");
128
129    CHECK(cudaFree(d_lane)); CHECK(cudaFree(d_all)); CHECK(cudaFree(d_any));
130    CHECK(cudaFree(d_shfl)); CHECK(cudaFree(d_up)); CHECK(cudaFree(d_down));
131    CHECK(cudaFree(d_xor)); CHECK(cudaFree(d_bpos)); CHECK(cudaFree(d_bzero));
132    return ok ? 0 : 1;
133}
binary_partition (test_web_cs_binarypart.cu:63)
53__global__ void oddEvenCountAndSumCG(int *inputArr, int *numOfOdds, int *sumOfOddAndEvens, unsigned int size)
54{
55    cg::thread_block          cta    = cg::this_thread_block();
56    cg::thread_block_tile<32> tile32 = cg::tiled_partition<32>(cta);
57
58    // [SIM] was: cg::grid_group grid = cg::this_grid();
59    //            for (int i = grid.thread_rank(); i < size; i += grid.size())
60    for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < (int)size;
61         i += gridDim.x * blockDim.x) {
62        int  elem    = inputArr[i];
63        auto subTile = cg::binary_partition(tile32, elem & 1);
64        if (elem & 1) // Odd numbers group
65        {
66            int oddGroupSum = cg::reduce(subTile, elem, cg::plus<int>());
67
68            if (subTile.thread_rank() == 0) {
69                // Add number of odds present in this group of Odds.
70                atomicAdd(numOfOdds, subTile.size());
71
72                // Add local reduction of odds present in this group of Odds.
73                atomicAdd(&sumOfOddAndEvens[0], oddGroupSum);
74            }
coalesced_threads (test_web_cs_warpaggr.cu:54)
44            std::exit(1);                                                      \
45        }                                                                      \
46    } while (0)
47
48const int NUM_ELEMS             = 1 << 16;   // [SIM] shrunk from 10000000
49const int NUM_THREADS_PER_BLOCK = 256;       // [SIM] source used 512
50
51// verbatim device code — warp-aggregated atomic increment
52__device__ int atomicAggInc(int *counter)
53{
54    cg::coalesced_group active = cg::coalesced_threads();
55
56    // leader does the update
57    int res = 0;
58    if (active.thread_rank() == 0) {
59        res = atomicAdd(counter, active.size());
60    }
61
62    // broadcast result
63    res = active.shfl(res, 0);
64
65    // each thread computes its own value
labeled_partition (test_web_cs_warpaggr_multi.cu:61)
51        cudaError_t _e = (call);                                                 \
52        if (_e != cudaSuccess) {                                                 \
53            std::printf("CUDA error %s at line %d\n", cudaGetErrorString(_e), __LINE__); \
54            g_ok = false;                                                        \
55        }                                                                        \
56    } while (0)
57
58// Warp-aggregated atomic multi-bucket increment (verbatim).
59__device__ int atomicAggIncMulti(const int bucket, int* counter) {
60    cg::coalesced_group active = cg::coalesced_threads();
61    auto labeledGroup = cg::labeled_partition(active, bucket);
62
63    int res = 0;
64    if (labeledGroup.thread_rank() == 0) res = atomicAdd(&counter[bucket], labeledGroup.size());
65    res = labeledGroup.shfl(res, 0);
66    return res + labeledGroup.thread_rank();
67}
68
69// Places individual value indices into their corresponding buckets (verbatim).
70__global__ void mapToBuckets(const int* srcArr, int* indicesBuckets, int* bucketCounters,
71                             const int srcSize, const int numOfBuckets) {
72    cg::grid_group grid = cg::this_grid();
meta_group_rank (test_coop_groups.cu:81)
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
85    int* d = nullptr;
86    CUDA_CHECK(cudaMalloc(&d, h.size() * sizeof(int)));
87    CUDA_CHECK(cudaMemcpy(d, h.data(), h.size() * sizeof(int), cudaMemcpyHostToDevice));
88    return d;
89}
90static bool report(const char* name, bool ok, unsigned seed) {
91    std::printf("  %-26s seed=%-5u %s\n", name, seed, ok ? "PASSED" : "FAILED");
92    return ok;
meta_group_size (test_web_cs_awbarrier.cu:78)
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        }
86
87        if (tile32.thread_rank() == 0) {
88            if (writeSquareRoot)
89                *result = sqrt(beta);
reduce (test_coop_groups.cu:73)
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
reduce (test_coop_groups.cu:73)
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
reduce (test_coop_groups.cu:73)
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
77__global__ void kTileInfo(int* rank, int* warp) {
78    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
79    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
80    rank[gid] = static_cast<int>(tile.thread_rank());
81    warp[gid] = static_cast<int>(tile.meta_group_rank());
82}
83
84static int* upload(const std::vector<int>& h) {
shfl (test_web_cs_warpaggr.cu:63)
53{
54    cg::coalesced_group active = cg::coalesced_threads();
55
56    // leader does the update
57    int res = 0;
58    if (active.thread_rank() == 0) {
59        res = atomicAdd(counter, active.size());
60    }
61
62    // broadcast result
63    res = active.shfl(res, 0);
64
65    // each thread computes its own value
66    return res + active.thread_rank();
67}
68
69// verbatim device code — filter positives, packing them via atomicAggInc
70__global__ void filter_arr(int *dst, int *nres, const int *src, int n)
71{
72    int id = threadIdx.x + blockIdx.x * blockDim.x;
73
74    for (int i = id; i < n; i += gridDim.x * blockDim.x) {
shfl_down (test_coop_groups.cu:65)
55    int bsum = reduce_sum(cg::this_thread_block(), temp, in[gid]);
56    if (threadIdx.x == 0) outBlk[blockIdx.x] = bsum;
57}
58
59// Warp-tile reduction via tile.shfl_down; rank 0 of each tile writes the sum.
60__global__ void kTileShfl(const int* in, int* outWarp) {
61    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
62    auto block = cg::this_thread_block();
63    auto tile  = cg::tiled_partition<32>(block);
64    int v = in[gid];
65    for (unsigned d = tile.size() / 2; d > 0; d >>= 1) v += tile.shfl_down(v, d);
66    if (tile.thread_rank() == 0) outWarp[gid / 32u] = v;
67}
68
69// cg::reduce broadcasts the warp sum to every lane.
70__global__ void kCgReduce(const int* in, int* out) {
71    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
72    auto tile = cg::tiled_partition<32>(cg::this_thread_block());
73    out[gid] = cg::reduce(tile, in[gid], cg::plus<int>());
74}
75
76// tile.thread_rank() and meta_group_rank() identify a lane and its warp.
size (test_coop_groups.cu:43)
33    } while (0)
34
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
54    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
size (test_coop_groups.cu:43)
33    } while (0)
34
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
54    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
sync (test_coop_groups.cu:45)
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
54    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
55    int bsum = reduce_sum(cg::this_thread_block(), temp, in[gid]);
56    if (threadIdx.x == 0) outBlk[blockIdx.x] = bsum;
sync (test_coop_groups.cu:45)
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
54    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
55    int bsum = reduce_sum(cg::this_thread_block(), temp, in[gid]);
56    if (threadIdx.x == 0) outBlk[blockIdx.x] = bsum;
sync (test_coop_groups.cu:45)
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
54    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
55    int bsum = reduce_sum(cg::this_thread_block(), temp, in[gid]);
56    if (threadIdx.x == 0) outBlk[blockIdx.x] = bsum;
sync (test_coop_groups.cu:45)
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
54    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
55    int bsum = reduce_sum(cg::this_thread_block(), temp, in[gid]);
56    if (threadIdx.x == 0) outBlk[blockIdx.x] = bsum;
sync (test_coop_groups.cu:45)
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
54    const unsigned gid = blockIdx.x * blockDim.x + threadIdx.x;
55    int bsum = reduce_sum(cg::this_thread_block(), temp, in[gid]);
56    if (threadIdx.x == 0) outBlk[blockIdx.x] = bsum;
this_grid (test_web_cs_awbarrier.cu:101)
 91                *result = beta;
 92        }
 93    }
 94}
 95#endif
 96
 97__global__ void normVecByDotProductAWBarrier(float* vecA, float* vecB,
 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);
thread_rank (test_coop_groups.cu:42)
32        }                                                                    \
33    } while (0)
34
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];
thread_rank (test_coop_groups.cu:42)
32        }                                                                    \
33    } while (0)
34
35constexpr int N     = 256;   // 8 warps
36constexpr int BLOCK = 128;   // 4 warps/block
37constexpr int WARPS = N / 32;
38
39// The CoffeeBeforeArch reduce_sum: reduce a thread_group to a single value in
40// thread 0, using shared scratch and group syncs.
41__device__ int reduce_sum(cg::thread_group g, int* temp, int val) {
42    int lane = static_cast<int>(g.thread_rank());
43    for (int i = static_cast<int>(g.size()) / 2; i > 0; i /= 2) {
44        temp[lane] = val;
45        g.sync();
46        if (lane < i) val += temp[lane + i];
47        g.sync();
48    }
49    return val;  // full sum in rank 0
50}
51
52__global__ void kBlockReduce(const int* in, int* outBlk) {
53    __shared__ int temp[BLOCK];