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 |
|---|---|---|---|---|
|
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 |
|
|
this_grid().sync() is a GRID-WIDE barrier. |
sim only |
simulator.h:1233 |
Structs#
Functions#
Signature |
Description |
Availability |
Location |
Example |
|---|---|---|---|---|
|
sim only |
simulator.h:1282 |
||
|
sim only |
simulator.h:1281 |
||
|
sim only |
simulator.h:1283 |
||
|
sim only |
simulator.h:1287 |
||
|
sim only |
simulator.h:1238 |
||
|
sim only |
simulator.h:1285 |
||
|
sim only |
simulator.h:1244 |
||
|
sim only |
simulator.h:1236 |
||
|
sim only |
simulator.h:1288 |
||
|
sim only |
simulator.h:1276 |
||
|
sim only |
simulator.h:1277 |
||
|
sim only |
simulator.h:1237 |
||
|
sim only |
simulator.h:1241 |
||
|
sim only |
simulator.h:1275 |
||
|
sim only |
simulator.h:1253 |
||
|
reduce over a singleton coalesced group returns the thread’s own value. |
sim only |
simulator.h:1290 |
|
|
sim only |
simulator.h:1291 |
||
|
sim only |
simulator.h:1278 |
||
|
sim only |
simulator.h:1280 |
||
|
sim only |
simulator.h:1279 |
||
|
sim only |
simulator.h:1242 |
||
|
sim only |
simulator.h:1274 |
||
|
sim only |
simulator.h:1235 |
||
|
sim only |
simulator.h:1247 |
||
|
Free sync() overloads (real CG provides sync(g) for every group type). |
sim only |
simulator.h:1259 |
|
|
sim only |
simulator.h:1272 |
||
|
sim only |
simulator.h:1286 |
||
|
sim only |
simulator.h:1246 |
||
|
sim only |
simulator.h:1243 |
||
|
sim only |
simulator.h:1273 |
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];