clr/hipamd/include/hip/amd_detail/amd_hip_cooperative_groups.h Source File

clr/hipamd/include/hip/amd_detail/amd_hip_cooperative_groups.h Source File#

HIP Runtime API Reference: clr/hipamd/include/hip/amd_detail/amd_hip_cooperative_groups.h Source File
amd_hip_cooperative_groups.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
16#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_H
17#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_H
18
19#if __cplusplus
20#if !defined(__HIPCC_RTC__)
21#include <hip/amd_detail/hip_cooperative_groups_helper.h>
22#endif
23
25 class thread_group;
26namespace impl {
27 template <typename TyGroup>
28__CG_QUALIFIER__ unsigned long long groupMask(const TyGroup&);
29}
30
40 template <typename TyGroup>
41 friend __CG_QUALIFIER__ unsigned long long cooperative_groups::impl::groupMask(const TyGroup&);
42 protected:
43 __hip_uint32_t _type;
44 __hip_uint32_t _num_threads;
45 __hip_uint64_t _mask;
52 __CG_QUALIFIER__ thread_group(internal::group_type type,
53 __hip_uint32_t num_threads = static_cast<__hip_uint64_t>(0),
54 __hip_uint64_t mask = static_cast<__hip_uint64_t>(0)) {
55 _type = type;
57 _mask = mask;
58 }
59
60 struct _tiled_info {
62 unsigned int num_threads;
63 unsigned int meta_group_rank;
64 unsigned int meta_group_size;
65 };
66
72
73 friend __CG_QUALIFIER__ thread_group this_thread();
74 friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent,
75 unsigned int tile_size);
76 friend class thread_block;
77
78 public:
82 __CG_QUALIFIER__ __hip_uint32_t num_threads() const { return _num_threads; }
84 __CG_QUALIFIER__ __hip_uint32_t size() const { return num_threads(); }
86 __CG_QUALIFIER__ unsigned int cg_type() const { return _type; }
88 __CG_QUALIFIER__ __hip_uint32_t thread_rank() const;
90 __CG_QUALIFIER__ __hip_uint32_t block_rank() const;
92 __CG_QUALIFIER__ bool is_valid() const;
93
106 __CG_QUALIFIER__ void sync() const;
107};
133 friend __CG_QUALIFIER__ multi_grid_group this_multi_grid();
134
135 protected:
137 explicit __CG_QUALIFIER__ multi_grid_group(__hip_uint32_t size)
138 : thread_group(internal::cg_multi_grid, size) {}
139
140 public:
143 __CG_QUALIFIER__ __hip_uint32_t num_grids() { return internal::multi_grid::num_grids(); }
144
147 __CG_QUALIFIER__ __hip_uint32_t grid_rank() { return internal::multi_grid::grid_rank(); }
149 __CG_QUALIFIER__ __hip_uint32_t thread_rank() const {
150 return internal::multi_grid::thread_rank();
151 }
153 __CG_QUALIFIER__ bool is_valid() const { return internal::multi_grid::is_valid(); }
155 __CG_QUALIFIER__ void sync() const { internal::multi_grid::sync(); }
156};
157
172 return multi_grid_group(internal::multi_grid::num_threads());
173}
174// Doxygen end group CooperativeGConstruct
185class grid_group : public thread_group {
188 friend __CG_QUALIFIER__ grid_group this_grid();
189
190 protected:
192 explicit __CG_QUALIFIER__ grid_group(__hip_uint32_t size)
193 : thread_group(internal::cg_grid, size) {}
194
195 public:
197 __CG_QUALIFIER__ __hip_uint32_t thread_rank() const { return internal::grid::thread_rank(); }
199 __CG_QUALIFIER__ __hip_uint32_t block_rank() const { return internal::grid::block_rank(); }
201 __CG_QUALIFIER__ bool is_valid() const { return internal::grid::is_valid(); }
203 __CG_QUALIFIER__ void sync() const { internal::grid::sync(); }
204 __CG_QUALIFIER__ dim3 group_dim() const { return internal::grid::grid_dim(); }
206 unsigned int signal;
207 };
209 __CG_QUALIFIER__ arrival_token barrier_arrive() const {
211 t.signal = internal::grid::barrier_signal();
212 return t;
213 }
215 __CG_QUALIFIER__ void barrier_wait(arrival_token&& t) const {
216 internal::grid::barrier_wait(t.signal);
217 }
218};
219
230__CG_QUALIFIER__ grid_group this_grid() { return grid_group(internal::grid::num_threads()); }
231
244 friend __CG_QUALIFIER__ thread_block this_thread_block();
245 friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent,
246 unsigned int tile_size);
247 friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_block& parent,
248 unsigned int tile_size);
249
250 protected:
251 // Construct a workgroup thread group (through the API this_thread_block())
252 explicit __CG_QUALIFIER__ thread_block(__hip_uint32_t size)
253 : thread_group(internal::cg_workgroup, size) {}
254
255 __CG_QUALIFIER__ thread_group new_tiled_group(unsigned int tile_size) const {
256 const bool pow2 = ((tile_size & (tile_size - 1)) == 0);
257 // Invalid tile size, assert
258 if (!tile_size || (tile_size > warpSize) || !pow2) {
259 __hip_assert(false && "invalid tile size");
260 }
261
262 auto block_size = num_threads();
263 auto rank = thread_rank();
264 auto partitions = (block_size + tile_size - 1) / tile_size;
265 auto tail = (partitions * tile_size) - block_size;
266 auto partition_size = tile_size - tail * (rank >= (partitions - 1) * tile_size);
267 thread_group tiledGroup = thread_group(internal::cg_tiled_group, partition_size);
268
269 tiledGroup.coalesced_info.tiled_info.num_threads = tile_size;
270 tiledGroup.coalesced_info.tiled_info.is_tiled = true;
271 tiledGroup.coalesced_info.tiled_info.meta_group_rank = rank / tile_size;
272 tiledGroup.coalesced_info.tiled_info.meta_group_size = partitions;
273 return tiledGroup;
274 }
275
276 public:
278 __CG_STATIC_QUALIFIER__ dim3 group_index() { return internal::workgroup::group_index(); }
280 __CG_STATIC_QUALIFIER__ dim3 thread_index() { return internal::workgroup::thread_index(); }
282 __CG_STATIC_QUALIFIER__ __hip_uint32_t thread_rank() {
283 return internal::workgroup::thread_rank();
284 }
286 __CG_STATIC_QUALIFIER__ __hip_uint32_t block_rank() {
287 return internal::workgroup::block_rank();
288 }
290 __CG_STATIC_QUALIFIER__ __hip_uint32_t num_threads() {
291 return internal::workgroup::num_threads();
292 }
294 __CG_STATIC_QUALIFIER__ __hip_uint32_t size() { return num_threads(); }
296 __CG_STATIC_QUALIFIER__ bool is_valid() { return internal::workgroup::is_valid(); }
298 __CG_STATIC_QUALIFIER__ void sync() { internal::workgroup::sync(); }
300 __CG_QUALIFIER__ dim3 group_dim() { return internal::workgroup::block_dim(); }
301 struct arrival_token {};
303 __CG_QUALIFIER__ arrival_token barrier_arrive() const {
304 internal::workgroup::barrier_arrive();
305 return arrival_token{};
306 }
308 __CG_QUALIFIER__ void barrier_wait(arrival_token&&) const { internal::workgroup::barrier_wait(); }
309};
310
321__CG_QUALIFIER__ thread_block this_thread_block() {
322 return thread_block(internal::workgroup::num_threads());
323}
324
332class tiled_group : public thread_group {
333 private:
334 friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent,
335 unsigned int tile_size);
336 friend __CG_QUALIFIER__ tiled_group tiled_partition(const tiled_group& parent,
337 unsigned int tile_size);
338
339 __CG_QUALIFIER__ tiled_group new_tiled_group(unsigned int tile_size) const {
340 const bool pow2 = ((tile_size & (tile_size - 1)) == 0);
341
342 if (!tile_size || (tile_size > warpSize) || !pow2) {
343 __hip_assert(false && "invalid tile size");
344 }
345
346 if (num_threads() <= tile_size) {
347 return *this;
348 }
349
350 tiled_group tiledGroup = tiled_group(tile_size);
351 tiledGroup.coalesced_info.tiled_info.is_tiled = true;
352 return tiledGroup;
353 }
354
355 protected:
356 explicit __CG_QUALIFIER__ tiled_group(unsigned int tileSize)
357 : thread_group(internal::cg_tiled_group, tileSize) {
360 }
361
362 public:
364 __CG_QUALIFIER__ unsigned int num_threads() const {
366 }
367
369 __CG_QUALIFIER__ unsigned int size() const { return num_threads(); }
370
372 __CG_QUALIFIER__ unsigned int thread_rank() const {
373 return (internal::workgroup::thread_rank() & (coalesced_info.tiled_info.num_threads - 1));
374 }
376 __CG_QUALIFIER__ void sync() const { internal::tiled_group::sync(); }
377};
378
379template <unsigned int size, class ParentCGTy> class thread_block_tile;
380
389 private:
390 friend __CG_QUALIFIER__ coalesced_group coalesced_threads();
391 friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent,
392 unsigned int tile_size);
393 friend __CG_QUALIFIER__ coalesced_group tiled_partition(const coalesced_group& parent,
394 unsigned int tile_size);
395 friend __CG_QUALIFIER__ coalesced_group binary_partition(const coalesced_group& cgrp, bool pred);
396
397 template <unsigned int fsize, class fparent> friend __CG_QUALIFIER__ coalesced_group
399
400 __CG_QUALIFIER__ coalesced_group new_tiled_group(unsigned int tile_size) const {
401 const bool pow2 = ((tile_size & (tile_size - 1)) == 0);
402
403 if (!tile_size || !pow2) {
404 return coalesced_group(0);
405 }
406
407 // If a tiled group is passed to be partitioned further into a coalesced_group.
408 // prepare a mask for further partitioning it so that it stays coalesced.
410 unsigned int base_offset = (thread_rank() & (~(tile_size - 1)));
411 unsigned int masklength =
412 min(static_cast<unsigned int>(num_threads()) - base_offset, tile_size);
413 lane_mask full_mask = (static_cast<int>(warpSize) == 32)
414 ? static_cast<lane_mask>((1u << 32) - 1)
415 : static_cast<lane_mask>(-1ull);
416 lane_mask member_mask = full_mask >> (warpSize - masklength);
417
418 member_mask <<= (__lane_id() & ~(tile_size - 1));
419 coalesced_group coalesced_tile = coalesced_group(member_mask);
420 coalesced_tile.coalesced_info.tiled_info.is_tiled = true;
421 coalesced_tile.coalesced_info.tiled_info.meta_group_rank = thread_rank() / tile_size;
422 coalesced_tile.coalesced_info.tiled_info.meta_group_size = num_threads() / tile_size;
423 return coalesced_tile;
424 }
425 // Here the parent coalesced_group is not partitioned.
426 else {
427 lane_mask member_mask = 0;
428 unsigned int tile_rank = 0;
429 int lanes_to_skip = ((thread_rank()) / tile_size) * tile_size;
430
431 for (unsigned int i = 0; i < warpSize; i++) {
432 lane_mask active = coalesced_info.member_mask & (static_cast<lane_mask>(1) << i);
433 // Make sure the lane is active
434 if (active) {
435 if (lanes_to_skip <= 0 && tile_rank < tile_size) {
436 // Prepare a member_mask that is appropriate for a tile
437 member_mask |= active;
438 tile_rank++;
439 }
440 lanes_to_skip--;
441 }
442 }
443 coalesced_group coalesced_tile = coalesced_group(member_mask);
444 coalesced_tile.coalesced_info.tiled_info.meta_group_rank = thread_rank() / tile_size;
445 coalesced_tile.coalesced_info.tiled_info.meta_group_size =
446 (num_threads() + tile_size - 1) / tile_size;
447 return coalesced_tile;
448 }
449 return coalesced_group(0);
450 }
451
452 protected:
453 // Constructor
454 explicit __CG_QUALIFIER__ coalesced_group(lane_mask member_mask)
455 : thread_group(internal::cg_coalesced_group) {
456 coalesced_info.member_mask = member_mask; // Which threads are active
458 __popcll(coalesced_info.member_mask); // How many threads are active
459 coalesced_info.tiled_info.is_tiled = false; // Not a partitioned group
462 }
463
464 public:
466 __CG_QUALIFIER__ unsigned int num_threads() const { return coalesced_info.num_threads; }
467
469 __CG_QUALIFIER__ unsigned int size() const { return num_threads(); }
470
472 __CG_QUALIFIER__ unsigned int thread_rank() const {
473 return internal::coalesced_group::masked_bit_count(coalesced_info.member_mask);
474 }
475
477 __CG_QUALIFIER__ void sync() const { internal::coalesced_group::sync(); }
478
481 __CG_QUALIFIER__ unsigned int meta_group_rank() const {
483 }
484
486 __CG_QUALIFIER__ unsigned int meta_group_size() const {
488 }
489
502 template <class T> __CG_QUALIFIER__ T shfl(T var, int srcRank) const {
503 srcRank = srcRank % static_cast<int>(num_threads());
504
505 int lane = (num_threads() == warpSize) ? srcRank
506 : (static_cast<int>(warpSize) == 64)
507 ? __fns64(coalesced_info.member_mask, 0, (srcRank + 1))
508 : __fns32(coalesced_info.member_mask, 0, (srcRank + 1));
509
510 return __shfl(var, lane, warpSize);
511 }
512
527 template <class T> __CG_QUALIFIER__ T shfl_down(T var, unsigned int lane_delta) const {
528 // Note: The cuda implementation appears to use the remainder of lane_delta
529 // and WARP_SIZE as the shift value rather than lane_delta itself.
530 // This is not described in the documentation and is not done here.
531
532 if (num_threads() == warpSize) {
533 return __shfl_down(var, lane_delta, warpSize);
534 }
535
536 int lane;
537 if (static_cast<int>(warpSize) == 64) {
538 lane = __fns64(coalesced_info.member_mask, __lane_id(), lane_delta + 1);
539 } else {
540 lane = __fns32(coalesced_info.member_mask, __lane_id(), lane_delta + 1);
541 }
542
543 if (lane == -1) {
544 lane = __lane_id();
545 }
546
547 return __shfl(var, lane, warpSize);
548 }
549
564 template <class T> __CG_QUALIFIER__ T shfl_up(T var, unsigned int lane_delta) const {
565 // Note: The cuda implementation appears to use the remainder of lane_delta
566 // and WARP_SIZE as the shift value rather than lane_delta itself.
567 // This is not described in the documentation and is not done here.
568
569 if (num_threads() == warpSize) {
570 return __shfl_up(var, lane_delta, warpSize);
571 }
572
573 int lane;
574 if (static_cast<int>(warpSize) == 64) {
575 lane = __fns64(coalesced_info.member_mask, __lane_id(), -(lane_delta + 1));
576 } else if (static_cast<int>(warpSize) == 32) {
577 lane = __fns32(coalesced_info.member_mask, __lane_id(), -(lane_delta + 1));
578 }
579
580 if (lane == -1) {
581 lane = __lane_id();
582 }
583
584 return __shfl(var, lane, warpSize);
585 }
586#if !defined(HIP_DISABLE_WARP_SYNC_BUILTINS)
587
595 __CG_QUALIFIER__ unsigned long long ballot(int pred) const {
596 return internal::helper::adjust_mask(
598 __ballot_sync<unsigned long long>(coalesced_info.member_mask, pred));
599 }
600
607 __CG_QUALIFIER__ int any(int pred) const {
608 return __any_sync(static_cast<unsigned long long>(coalesced_info.member_mask), pred);
609 }
610
617 __CG_QUALIFIER__ int all(int pred) const {
618 return __all_sync(static_cast<unsigned long long>(coalesced_info.member_mask), pred);
619 }
620
629 template <typename T> __CG_QUALIFIER__ unsigned long long match_any(T value) const {
630 return internal::helper::adjust_mask(
632 __match_any_sync(static_cast<unsigned long long>(coalesced_info.member_mask), value));
633 }
634
646 template <typename T> __CG_QUALIFIER__ unsigned long long match_all(T value, int& pred) const {
647 return internal::helper::adjust_mask(
649 __match_all_sync(static_cast<unsigned long long>(coalesced_info.member_mask), value,
650 &pred));
651 }
652#endif // HIP_DISABLE_WARP_SYNC_BUILTINS
653};
654
665 __builtin_amdgcn_is_invocable(__builtin_amdgcn_read_exec)
666 ? __builtin_amdgcn_read_exec()
667 : 0);
668}
669
670#ifndef DOXYGEN_SHOULD_SKIP_THIS
671
677__CG_QUALIFIER__ __hip_uint32_t thread_group::thread_rank() const {
678 switch (this->_type) {
679 case internal::cg_multi_grid: {
680 return (static_cast<const multi_grid_group*>(this)->thread_rank());
681 }
682 case internal::cg_grid: {
683 return (static_cast<const grid_group*>(this)->thread_rank());
684 }
685 case internal::cg_workgroup: {
686 return (static_cast<const thread_block*>(this)->thread_rank());
687 }
688 case internal::cg_tiled_group: {
689 return (static_cast<const tiled_group*>(this)->thread_rank());
690 }
691 case internal::cg_coalesced_group: {
692 return (static_cast<const coalesced_group*>(this)->thread_rank());
693 }
694 default: {
695 __hip_assert(false && "invalid cooperative group type");
696 return -1;
697 }
698 }
699}
700
706__CG_QUALIFIER__ bool thread_group::is_valid() const {
707 switch (this->_type) {
708 case internal::cg_multi_grid: {
709 return (static_cast<const multi_grid_group*>(this)->is_valid());
710 }
711 case internal::cg_grid: {
712 return (static_cast<const grid_group*>(this)->is_valid());
713 }
714 case internal::cg_workgroup: {
715 return (static_cast<const thread_block*>(this)->is_valid());
716 }
717 case internal::cg_tiled_group: {
718 return (static_cast<const tiled_group*>(this)->is_valid());
719 }
720 case internal::cg_coalesced_group: {
721 return (static_cast<const coalesced_group*>(this)->is_valid());
722 }
723 default: {
724 __hip_assert(false && "invalid cooperative group type");
725 return false;
726 }
727 }
728}
729
735__CG_QUALIFIER__ void thread_group::sync() const {
736 switch (this->_type) {
737 case internal::cg_multi_grid: {
738 static_cast<const multi_grid_group*>(this)->sync();
739 break;
740 }
741 case internal::cg_grid: {
742 static_cast<const grid_group*>(this)->sync();
743 break;
744 }
745 case internal::cg_workgroup: {
746 static_cast<const thread_block*>(this)->sync();
747 break;
748 }
749 case internal::cg_tiled_group: {
750 static_cast<const tiled_group*>(this)->sync();
751 break;
752 }
753 case internal::cg_coalesced_group: {
754 static_cast<const coalesced_group*>(this)->sync();
755 break;
756 }
757 default: {
758 __hip_assert(false && "invalid cooperative group type");
759 }
760 }
761#if __has_builtin(__builtin_amdgcn_s_wait_asynccnt)
762 if (__builtin_amdgcn_is_invocable(__builtin_amdgcn_s_wait_asynccnt))
763 __builtin_amdgcn_s_wait_asynccnt(0);
764#endif
765}
766
767#endif
768
786template <class CGTy> __CG_QUALIFIER__ __hip_uint32_t group_size(CGTy const& g) {
787 return g.num_threads();
788}
789
801template <class CGTy> __CG_QUALIFIER__ __hip_uint32_t thread_rank(CGTy const& g) {
802 return g.thread_rank();
803}
804
814template <class CGTy> __CG_QUALIFIER__ bool is_valid(CGTy const& g) { return g.is_valid(); }
815
825template <class CGTy> __CG_QUALIFIER__ void sync(CGTy const& g) { g.sync(); }
826
827// Doxygen end group CooperativeGAPI
835template <unsigned int tileSize> class tile_base {
836 protected:
837 _CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
838
839 public:
841 _CG_STATIC_CONST_DECL_ unsigned int thread_rank() {
842 return (internal::workgroup::thread_rank() & (numThreads - 1));
843 }
844
846 __CG_STATIC_QUALIFIER__ unsigned int num_threads() { return numThreads; }
847
850 __CG_STATIC_QUALIFIER__ unsigned int size() { return num_threads(); }
851};
852
858template <unsigned int size> class thread_block_tile_base : public tile_base<size> {
859 static_assert(is_valid_tile_size<size>::value,
860 "Tile size is either not a power of 2 or greater than the wavefront size");
862
863 template <unsigned int fsize, class fparent> friend __CG_QUALIFIER__ coalesced_group
865
866#if !defined(HIP_DISABLE_WARP_SYNC_BUILTINS)
867 __CG_QUALIFIER__ unsigned long long build_mask() const {
868 unsigned long long mask = ~0ull >> (64 - numThreads);
869 // thread_rank() gives thread id from 0..thread launch size.
870 return mask << (((internal::workgroup::thread_rank() % warpSize) / numThreads) * numThreads);
871 }
872#endif // HIP_DISABLE_WARP_SYNC_BUILTINS
873
874 public:
875 __CG_STATIC_QUALIFIER__ void sync() { internal::tiled_group::sync(); }
876
877 template <class T> __CG_QUALIFIER__ T shfl(T var, int srcRank) const {
878 return (__shfl(var, srcRank, numThreads));
879 }
880
881 template <class T> __CG_QUALIFIER__ T shfl_down(T var, unsigned int lane_delta) const {
882 return (__shfl_down(var, lane_delta, numThreads));
883 }
884
885 template <class T> __CG_QUALIFIER__ T shfl_up(T var, unsigned int lane_delta) const {
886 return (__shfl_up(var, lane_delta, numThreads));
887 }
888
889 template <class T> __CG_QUALIFIER__ T shfl_xor(T var, unsigned int laneMask) const {
890 return (__shfl_xor(var, laneMask, numThreads));
891 }
892
893#if !defined(HIP_DISABLE_WARP_SYNC_BUILTINS)
894 __CG_QUALIFIER__ unsigned long long ballot(int pred) const {
895 const auto mask = build_mask();
896 return internal::helper::adjust_mask(mask, __ballot_sync(mask, pred));
897 }
898
899 __CG_QUALIFIER__ int any(int pred) const { return __any_sync(build_mask(), pred); }
900
901 __CG_QUALIFIER__ int all(int pred) const { return __all_sync(build_mask(), pred); }
902
903 template <typename T> __CG_QUALIFIER__ unsigned long long match_any(T value) const {
904 const auto mask = build_mask();
905 return internal::helper::adjust_mask(mask, __match_any_sync(mask, value));
906 }
907
908 template <typename T> __CG_QUALIFIER__ unsigned long long match_all(T value, int& pred) const {
909 const auto mask = build_mask();
910 return internal::helper::adjust_mask(mask, __match_all_sync(mask, value, &pred));
911 }
912#endif // HIP_DISABLE_WARP_SYNC_BUILTINS
913};
914
917template <unsigned int tileSize, typename ParentCGTy> class parent_group_info {
918 public:
921 __CG_STATIC_QUALIFIER__ unsigned int meta_group_rank() {
922 return ParentCGTy::thread_rank() / tileSize;
923 }
924
926 __CG_STATIC_QUALIFIER__ unsigned int meta_group_size() {
927 return (ParentCGTy::num_threads() + tileSize - 1) / tileSize;
928 }
929};
930
937template <unsigned int tileSize, class ParentCGTy> class thread_block_tile_type
938 : public thread_block_tile_base<tileSize>,
939 public tiled_group,
940 public parent_group_info<tileSize, ParentCGTy> {
941 _CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
943
944 protected:
945 __CG_QUALIFIER__ thread_block_tile_type() : tiled_group(numThreads) {
948 }
949
958
959 public:
961 using tbtBase::size;
964};
965
966// Partial template specialization
967template <unsigned int tileSize> class thread_block_tile_type<tileSize, void>
968 : public thread_block_tile_base<tileSize>, public tiled_group {
969 _CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
970
972
973 protected:
982
983 public:
985 using tbtBase::size;
986 using tbtBase::sync;
988
991 __CG_QUALIFIER__ unsigned int meta_group_rank() const {
993 }
994
996 __CG_QUALIFIER__ unsigned int meta_group_size() const {
998 }
999 // Doxygen end group CooperativeG
1003};
1004
1005__CG_QUALIFIER__ thread_group this_thread() {
1006 thread_group g(internal::group_type::cg_coalesced_group, 1, __ockl_activelane_u32());
1007 return g;
1008}
1009
1017__CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent, unsigned int tile_size) {
1018 if (parent.cg_type() == internal::cg_tiled_group) {
1019 const tiled_group* cg = static_cast<const tiled_group*>(&parent);
1020 return cg->new_tiled_group(tile_size);
1021 } else if (parent.cg_type() == internal::cg_coalesced_group) {
1022 const coalesced_group* cg = static_cast<const coalesced_group*>(&parent);
1023 return cg->new_tiled_group(tile_size);
1024 } else {
1025 const thread_block* tb = static_cast<const thread_block*>(&parent);
1026 return tb->new_tiled_group(tile_size);
1027 }
1028}
1029
1030// Thread block type overload
1031__CG_QUALIFIER__ thread_group tiled_partition(const thread_block& parent, unsigned int tile_size) {
1032 return (parent.new_tiled_group(tile_size));
1033}
1034
1035__CG_QUALIFIER__ tiled_group tiled_partition(const tiled_group& parent, unsigned int tile_size) {
1036 return (parent.new_tiled_group(tile_size));
1037}
1038
1039// If a coalesced group is passed to be partitioned, it should remain coalesced
1040__CG_QUALIFIER__ coalesced_group tiled_partition(const coalesced_group& parent,
1041 unsigned int tile_size) {
1042 return (parent.new_tiled_group(tile_size));
1043}
1044
1045namespace impl {
1046template <unsigned int size, class ParentCGTy> class thread_block_tile_internal;
1047
1048template <unsigned int size, class ParentCGTy> class thread_block_tile_internal
1049 : public thread_block_tile_type<size, ParentCGTy> {
1050 protected:
1051 template <unsigned int tbtSize, class tbtParentT> __CG_QUALIFIER__ thread_block_tile_internal(
1054
1055 __CG_QUALIFIER__ thread_block_tile_internal(const thread_block& g)
1056 : thread_block_tile_type<size, ParentCGTy>() {}
1057};
1058
1059// becomes to std::true_type if the group is tiled and has a size known at compile time
1060template <class TyGroup>
1061struct isTiledGroup : __hip_internal::false_type {
1062};
1063
1064template <unsigned int N, class ParentCGTy>
1066 : __hip_internal::integral_constant<bool,
1067 (N == 1 || N == 2 || N == 4 || N == 8 ||
1068 N == 16 || N == 32 || N == 64)> {
1069};
1070
1071// returns the size of tile_group provided it is known at compile time
1072template <class TyGroup>
1073struct tiledGroupSize : __hip_internal::integral_constant<int, 0> {
1074
1075};
1076template <unsigned int N, class ParentCGTy>
1078 : __hip_internal::integral_constant<int, N> {
1079};
1080
1081template <class TyGroup>
1082struct isCoalescedGroup : __hip_internal::false_type {
1083};
1084
1085template <>
1086struct isCoalescedGroup<cooperative_groups::coalesced_group> : __hip_internal::true_type {
1087};
1088} // namespace impl
1089
1098template <unsigned int size, class ParentCGTy> class thread_block_tile
1099 : public impl::thread_block_tile_internal<size, ParentCGTy> {
1100 protected:
1101 __CG_QUALIFIER__ thread_block_tile(const ParentCGTy& g)
1102 : impl::thread_block_tile_internal<size, ParentCGTy>(g) {}
1103
1104 public:
1105 __CG_QUALIFIER__ operator thread_block_tile<size, void>() const {
1106 return thread_block_tile<size, void>(*this);
1107 }
1108
1109#ifdef DOXYGEN_SHOULD_INCLUDE_THIS
1110
1112 __CG_QUALIFIER__ unsigned int thread_rank() const;
1113
1115 __CG_QUALIFIER__ void sync();
1116
1119 __CG_QUALIFIER__ unsigned int meta_group_rank() const;
1120
1122 __CG_QUALIFIER__ unsigned int meta_group_size() const;
1123
1136 template <class T> __CG_QUALIFIER__ T shfl(T var, int srcRank) const;
1137
1152 template <class T> __CG_QUALIFIER__ T shfl_down(T var, unsigned int lane_delta) const;
1153
1168 template <class T> __CG_QUALIFIER__ T shfl_up(T var, unsigned int lane_delta) const;
1169
1182 template <class T> __CG_QUALIFIER__ T shfl_xor(T var, unsigned int laneMask) const;
1183
1191 __CG_QUALIFIER__ unsigned long long ballot(int pred) const;
1192
1199 __CG_QUALIFIER__ int any(int pred) const;
1200
1207 __CG_QUALIFIER__ int all(int pred) const;
1208
1217 template <typename T> __CG_QUALIFIER__ unsigned long long match_any(T value) const;
1218
1230 template <typename T> __CG_QUALIFIER__ unsigned long long match_all(T value, int& pred) const;
1231
1232#endif
1233};
1234
1235template <unsigned int size> class thread_block_tile<size, void>
1236 : public impl::thread_block_tile_internal<size, void> {
1237 template <unsigned int, class ParentCGTy> friend class thread_block_tile;
1238
1239 protected:
1240 public:
1241 template <class ParentCGTy>
1243 : impl::thread_block_tile_internal<size, void>(g) {}
1244};
1245
1246template <unsigned int size, class ParentCGTy = void> class thread_block_tile;
1247
1248namespace impl {
1249template <unsigned int size, class ParentCGTy> struct tiled_partition_internal;
1250
1251template <unsigned int size> struct tiled_partition_internal<size, thread_block>
1252 : public thread_block_tile<size, thread_block> {
1255};
1256
1257// ParentCGTy = thread_block_tile<ParentSize, GrandParentCGTy> specialization
1258template <unsigned int size, unsigned int ParentSize, class GrandParentCGTy>
1259struct tiled_partition_internal<size, thread_block_tile<ParentSize, GrandParentCGTy> >
1260 : public thread_block_tile<size, thread_block_tile<ParentSize, GrandParentCGTy> > {
1261 static_assert(size < ParentSize, "Sub tile size must be < parent tile size in tiled_partition");
1262
1264 : thread_block_tile<size, thread_block_tile<ParentSize, GrandParentCGTy> >(g) {}
1265};
1266
1267} // namespace impl
1268
1281template <unsigned int size, class ParentCGTy>
1282__CG_QUALIFIER__ thread_block_tile<size, ParentCGTy> tiled_partition(const ParentCGTy& g) {
1283 static_assert(is_valid_tile_size<size>::value,
1284 "Tiled partition with size > wavefront size. Currently not supported ");
1286}
1287
1288#if !defined(HIP_DISABLE_WARP_SYNC_BUILTINS)
1289
1298__CG_QUALIFIER__ coalesced_group binary_partition(const coalesced_group& cgrp, bool pred) {
1299 auto mask = __ballot_sync<unsigned long long>(cgrp.coalesced_info.member_mask, pred);
1300
1301 if (pred) {
1302 return coalesced_group(mask);
1303 } else {
1304 return coalesced_group(cgrp.coalesced_info.member_mask ^ mask);
1305 }
1306}
1307
1319template <unsigned int size, class parent>
1321 bool pred) {
1322 auto mask = __ballot_sync<unsigned long long>(tgrp.build_mask(), pred);
1323
1324 if (pred) {
1325 return coalesced_group(mask);
1326 } else {
1327 return coalesced_group(tgrp.build_mask() ^ mask);
1328 }
1329}
1330
1331
1332template <class T>
1333struct plus {
1334 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1335 {
1336 return lhs + rhs;
1337 }
1338};
1339
1340template <class T>
1341struct less {
1342 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1343 {
1344 return lhs < rhs? lhs : rhs;
1345 }
1346};
1347
1348template <class T>
1349struct greater {
1350 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1351 {
1352 return lhs < rhs? rhs : lhs;
1353 }
1354};
1355
1356template <class T>
1357struct bit_and {
1358 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1359 {
1360 return lhs & rhs;
1361 }
1362};
1363
1364template <class T>
1365struct bit_xor {
1366 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1367 {
1368 return lhs ^ rhs;
1369 }
1370};
1371
1372template <class T>
1373struct bit_or {
1374 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1375 {
1376 return lhs | rhs;
1377 }
1378};
1379
1380namespace impl {
1381// when instantiated with two parameter types, allows to know if there are the same, regardless
1382// of const/volatile qualifiers
1383template <typename T, typename U>
1384using is_param_type_same = __hip_internal::is_same<typename __hip_internal::remove_cvref<T>,
1385 typename __hip_internal::remove_cvref<U>>;
1386
1387template <class T, class Op>
1388struct isArithmeticFunc : __hip_internal::false_type {
1389};
1390
1391template <class T>
1392struct isArithmeticFunc<T, cooperative_groups::plus<T>> : __hip_internal::true_type {
1393};
1394
1395template <class T>
1396struct isArithmeticFunc<T, cooperative_groups::less<T>> : __hip_internal::true_type {
1397};
1398
1399template <class T>
1400struct isArithmeticFunc<T, cooperative_groups::greater<T>> : __hip_internal::true_type {
1401};
1402
1403template <class T, class Op>
1404struct isBooleanFunc : __hip_internal::false_type {
1405};
1406
1407template <class T>
1408struct isBooleanFunc<T, cooperative_groups::bit_and<T>> : __hip_internal::true_type {
1409};
1410
1411template <class T>
1412struct isBooleanFunc<T, cooperative_groups::bit_or<T>> : __hip_internal::true_type {
1413};
1414
1415template <class T>
1416struct isBooleanFunc<T, cooperative_groups::bit_xor<T>> : __hip_internal::true_type {
1417};
1418
1419// this is the value to return in exclusive_scan, for lane 0
1420template <class T, class Op>
1423 {
1424 T result = {};
1425 return result;
1426 }
1427};
1428
1429template <class T>
1432 {
1433 T result {};
1434 return ~result;
1435 }
1436};
1437
1438template <class T>
1441 {
1442 // CUDA would return 0 in this case. But in our case we mimic what __ockl_wfscan_*
1443 // would do
1444 return __hip_internal::NumericLimits<T>::maximum();
1445 }
1446};
1447
1448template <class T>
1451 {
1452 return __hip_internal::NumericLimits<T>::minimum();
1453 }
1454};
1455
1456// calculates the necessary warp mask for cooperative groups that support reduce(), or
1457// inclusive/exlcusive_scan()
1458template <typename TyGroup>
1459__CG_QUALIFIER__ unsigned long long groupMask(const TyGroup& group)
1460{
1461 unsigned long long mask = ~0ull;
1462
1464 mask = group.coalesced_info.member_mask;
1465 } else {
1466 // we cannot simply just use the __activemask() here, because more than one tile could have active
1467 // threads at a time; we need to mask away the threads that not part of this tile first
1468 mask >>= (64 - group.num_threads());
1469 mask <<= (((internal::workgroup::thread_rank() % warpSize) / group.num_threads()) * group.num_threads());
1470 }
1471
1472 return mask;
1473}
1474
1475// backward permute implementation for cooperative group operations, i.e.
1476// for up to 32 bytes (__hip_ds_bpermute() can only do 4 bytes at a time,
1477// this function calls it (or the floating point version) multiple times to
1478// implement it for bigger sizes
1479template <bool isPrimitiveType, class T, size_t NumPermutes, typename __hip_internal::enable_if<NumPermutes == 0, int>::type = 0>
1481{
1482}
1483
1484// trivial case: the type fits within the permute size
1485template <bool IsPrimitiveType, class T, size_t NumPermutes, typename __hip_internal::enable_if<IsPrimitiveType && NumPermutes == 1, int>::type = 0>
1486__CG_QUALIFIER__ void bPermute(T& permuteResult, T result, int from)
1487{
1488 auto backwardPermute = [](int index, T arg) {
1489 if constexpr (__hip_internal::is_floating_point<T>::value &&
1490 sizeof(T) <= 4) {
1491 return __hip_ds_bpermutef(index, arg);
1492 } else {
1493 return __hip_ds_bpermute(index, arg);
1494 }
1495 };
1496
1497 if constexpr (sizeof(T) == 2) {
1498 union {
1499 int i;
1500 T f;
1501 } tmp;
1502
1503 tmp.f = result;
1504 tmp.i = __hip_ds_bpermute(from << 2, tmp.i);
1505 permuteResult = tmp.f;
1506 } else if constexpr (sizeof(T) == 4) {
1507 auto bPermuteResult = backwardPermute(from << 2, result);
1508 __builtin_memcpy(&permuteResult, &bPermuteResult, sizeof(result));
1509 } else {
1510 static_assert(__hip_internal::is_void<T>::value, "Unexpected type");
1511 }
1512}
1513
1514// Overload when we need multiple ds_permute, because one is not enough
1515template <bool IsPrimitiveType, class T, size_t NumPermutes>
1517{
1518 // ds_bpermute only deals with 32-bit sizes, so for other sizes
1519 // we need to call the permute multiple times
1520 for (int i = 0; i < NumPermutes; i++) {
1522 }
1523}
1524
1525} // namespace impl
1526#endif
1527
1535 friend __CG_QUALIFIER__ cluster_group this_cluster();
1536
1537 // Default constructor, hidden
1538 __CG_QUALIFIER__ cluster_group() {}
1539
1540 public:
1541 using arrival_token = struct {};
1542
1543 // Sync the cluster, equivalent to c.barrier_wait(c.barrier_arrive());
1544 __CG_STATIC_QUALIFIER__ void sync() { internal::cluster::sync(); }
1545
1546 // Arrive on a cluster barrier, returns token that needs to be passed to barrier_wait
1547 __CG_STATIC_QUALIFIER__ arrival_token barrier_arrive() {
1548 // signal user cluster barrier
1549 internal::cluster::barrier_arrive();
1550 return arrival_token();
1551 }
1552
1553 // Wait on arrival_token
1554 __CG_STATIC_QUALIFIER__ void barrier_wait(arrival_token&&) { internal::cluster::barrier_wait(); }
1555
1556 // TODO: implement this when compiler work is done
1557 // block rank to which shared memory address belongs to
1558 // __CG_STATIC_QUALIFIER__ unsigned int query_shared_rank(const void* addr) {}
1559 // Obtain the address of shared memory variable of another block in the cluster
1560 // template <typename T> __CG_STATIC_QUALIFIER__ T* map_shared_rank(T* addr, int rank) {}
1561
1562 // index of the calling block within cluster
1563 __CG_STATIC_QUALIFIER__ dim3 block_index() { return internal::cluster::block_index(); }
1564
1565 // Rank of calling block within [0, num_blocks)
1566 __CG_STATIC_QUALIFIER__ unsigned int block_rank() { return internal::cluster::block_rank(); }
1567
1568 // index of the calling thread within cluster
1569 __CG_STATIC_QUALIFIER__ dim3 thread_index() { return internal::cluster::thread_index(); }
1570
1571 // Rank of calling thread within [0, num_threads)
1572 __CG_STATIC_QUALIFIER__ unsigned int thread_rank() { return internal::cluster::thread_rank(); }
1573
1574 // Dimensions of launched cluster in unit of blocks
1575 __CG_STATIC_QUALIFIER__ dim3 dim_blocks() { return internal::cluster::dim_blocks(); }
1576
1577 // total number of blocks in the group
1578 __CG_STATIC_QUALIFIER__ unsigned int num_blocks() { return internal::cluster::num_blocks(); }
1579
1580 // Dimensions of launched cluster in unit of threads
1581 __CG_STATIC_QUALIFIER__ dim3 dim_threads() { return internal::cluster::dim_threads(); }
1582
1583 // Total number of threads in the group
1584 __CG_STATIC_QUALIFIER__ unsigned int num_threads() { return internal::cluster::num_threads(); }
1585
1586 // Get address of shared memory variable in another cluster
1587 template <typename T> __CG_STATIC_QUALIFIER__ T* map_shared_rank(T* in, int rank) {
1588 return internal::cluster::map_shared_rank<T>(in, rank);
1589 }
1590
1591 // Return block rank of shared memory address
1592 __CG_STATIC_QUALIFIER__ unsigned int query_shared_rank(const void* in) {
1593 return internal::cluster::query_shared_rank(in);
1594 }
1595
1596 // Alias of num_threads
1597 __CG_STATIC_QUALIFIER__ unsigned int size() { return num_threads(); }
1598};
1599
1605__CG_QUALIFIER__ cluster_group this_cluster() {
1606 cluster_group cg;
1607 return cg;
1608}
1609} // namespace cooperative_groups
1610
1611#endif // __cplusplus
1612#endif // HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_H
Cluster group.
Definition amd_hip_cooperative_groups.h:1534
static unsigned int query_shared_rank(const void *in)
Definition amd_hip_cooperative_groups.h:1592
static unsigned int thread_rank()
Definition amd_hip_cooperative_groups.h:1572
static dim3 thread_index()
Definition amd_hip_cooperative_groups.h:1569
static T * map_shared_rank(T *in, int rank)
Definition amd_hip_cooperative_groups.h:1587
static void sync()
Definition amd_hip_cooperative_groups.h:1544
{} arrival_token
Definition amd_hip_cooperative_groups.h:1541
static dim3 block_index()
Definition amd_hip_cooperative_groups.h:1563
static void barrier_wait(arrival_token &&)
Definition amd_hip_cooperative_groups.h:1554
static unsigned int block_rank()
Definition amd_hip_cooperative_groups.h:1566
static unsigned int num_threads()
Definition amd_hip_cooperative_groups.h:1584
static unsigned int size()
Definition amd_hip_cooperative_groups.h:1597
static arrival_token barrier_arrive()
Definition amd_hip_cooperative_groups.h:1547
static unsigned int num_blocks()
Definition amd_hip_cooperative_groups.h:1578
friend cluster_group this_cluster()
get cluster group
Definition amd_hip_cooperative_groups.h:1605
static dim3 dim_threads()
Definition amd_hip_cooperative_groups.h:1581
static dim3 dim_blocks()
Definition amd_hip_cooperative_groups.h:1575
The coalesced_group cooperative group type.
Definition amd_hip_cooperative_groups.h:388
The grid cooperative group type.
Definition amd_hip_cooperative_groups.h:185
Definition amd_hip_cooperative_groups.h:1049
thread_block_tile_internal(const thread_block &g)
Definition amd_hip_cooperative_groups.h:1055
thread_block_tile_internal(const thread_block_tile_internal< tbtSize, tbtParentT > &g)
Definition amd_hip_cooperative_groups.h:1051
The multi-grid cooperative group type.
Definition amd_hip_cooperative_groups.h:130
User exposed API that captures the state of the parent group pre-partition.
Definition amd_hip_cooperative_groups.h:917
thread_block_tile(const thread_block_tile< size, ParentCGTy > &g)
Definition amd_hip_cooperative_groups.h:1242
Definition amd_hip_cooperative_groups.h:858
Group type - thread_block_tile.
Definition amd_hip_cooperative_groups.h:940
Group type - thread_block_tile.
Definition amd_hip_cooperative_groups.h:1099
T shfl_down(T var, unsigned int lane_delta) const
Shuffle down operation on group level.
int any(int pred) const
Any function on group level.
unsigned long long ballot(int pred) const
Ballot function on group level.
thread_block_tile(const ParentCGTy &g)
Definition amd_hip_cooperative_groups.h:1101
unsigned int meta_group_rank() const
unsigned int thread_rank() const
Rank of the calling thread within [0, num_threads() ).
T shfl_xor(T var, unsigned int laneMask) const
Shuffle xor operation on group level.
int all(int pred) const
All function on group level.
unsigned long long match_any(T value) const
Match any function on group level.
unsigned long long match_all(T value, int &pred) const
Match all function on group level.
unsigned int meta_group_size() const
Returns the number of groups created when the parent group was partitioned.
T shfl_up(T var, unsigned int lane_delta) const
Shuffle up operation on group level.
void sync()
Synchronizes the threads in the group.
T shfl(T var, int srcRank) const
Shuffle operation on group level.
The workgroup (thread-block in CUDA terminology) cooperative group type.
Definition amd_hip_cooperative_groups.h:241
The base type of all cooperative group types.
Definition amd_hip_cooperative_groups.h:39
Definition amd_hip_cooperative_groups.h:835
The tiled_group cooperative group type.
Definition amd_hip_cooperative_groups.h:332
const struct texture< T, dim, readMode > const void size_t size
Definition hip_runtime_api.h:10563
bool is_valid(CGTy const &g)
Returns true if the group has not violated any API constraints.
Definition amd_hip_cooperative_groups.h:814
void sync(CGTy const &g)
Synchronizes the threads in the group.
Definition amd_hip_cooperative_groups.h:825
__hip_uint32_t group_size(CGTy const &g)
Returns the size of the group.
Definition amd_hip_cooperative_groups.h:786
__hip_uint32_t thread_rank(CGTy const &g)
Returns the rank of thread of the group.
Definition amd_hip_cooperative_groups.h:801
thread_block this_thread_block()
User-exposed API interface to construct workgroup cooperative group type object - thread_block.
Definition amd_hip_cooperative_groups.h:321
coalesced_group binary_partition(const coalesced_group &cgrp, bool pred)
Binary partition.
Definition amd_hip_cooperative_groups.h:1298
thread_group tiled_partition(const thread_group &parent, unsigned int tile_size)
User-exposed API to partition groups.
Definition amd_hip_cooperative_groups.h:1017
multi_grid_group this_multi_grid()
User-exposed API interface to construct grid cooperative group type object - multi_grid_group.
Definition amd_hip_cooperative_groups.h:171
coalesced_group coalesced_threads()
User-exposed API to create coalesced groups.
Definition amd_hip_cooperative_groups.h:663
grid_group this_grid()
User-exposed API interface to construct grid cooperative group type object - grid_group.
Definition amd_hip_cooperative_groups.h:230
void sync() const
Synchronizes the threads in the group.
Definition amd_hip_cooperative_groups.h:376
T shfl_xor(T var, unsigned int laneMask) const
Definition amd_hip_cooperative_groups.h:889
static constexpr unsigned int numThreads
Definition amd_hip_cooperative_groups.h:837
friend multi_grid_group this_multi_grid()
User-exposed API interface to construct grid cooperative group type object - multi_grid_group.
Definition amd_hip_cooperative_groups.h:171
void sync() const
Synchronizes the threads in the group.
Definition amd_hip_cooperative_groups.h:477
static void sync()
Definition amd_hip_cooperative_groups.h:875
void barrier_wait(arrival_token &&t) const
Arrive at a barrier.
Definition amd_hip_cooperative_groups.h:215
unsigned int num_threads
Definition amd_hip_cooperative_groups.h:62
__hip_uint32_t thread_rank() const
Rank of the calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:197
arrival_token barrier_arrive() const
Arrive at a barrier.
Definition amd_hip_cooperative_groups.h:209
void sync() const
Synchronizes the threads in the group.
Definition amd_hip_cooperative_groups.h:203
__hip_uint32_t size() const
Total number of threads in the group (alias of num_threads())
Definition amd_hip_cooperative_groups.h:84
unsigned int size() const
Total number of threads in the group (alias of num_threads())
Definition amd_hip_cooperative_groups.h:469
__hip_uint32_t num_grids()
Definition amd_hip_cooperative_groups.h:143
unsigned long long match_all(T value, int &pred) const
Definition amd_hip_cooperative_groups.h:908
unsigned long long match_any(T value) const
Match any function on group level.
Definition amd_hip_cooperative_groups.h:629
friend thread_block this_thread_block()
User-exposed API interface to construct workgroup cooperative group type object - thread_block.
Definition amd_hip_cooperative_groups.h:321
static unsigned int meta_group_size()
Returns the number of groups created when the parent group was partitioned.
Definition amd_hip_cooperative_groups.h:926
unsigned int signal
Definition amd_hip_cooperative_groups.h:206
unsigned int meta_group_rank() const
Definition amd_hip_cooperative_groups.h:481
dim3 group_dim() const
Definition amd_hip_cooperative_groups.h:204
unsigned int meta_group_rank() const
Definition amd_hip_cooperative_groups.h:991
__hip_uint32_t _num_threads
Type of the thread_group.
Definition amd_hip_cooperative_groups.h:44
__hip_uint32_t block_rank() const
Rank of the block in calling thread within [0, num_threads() ).
static unsigned int num_threads()
Number of threads within this tile.
Definition amd_hip_cooperative_groups.h:846
thread_group(internal::group_type type, __hip_uint32_t num_threads=static_cast< __hip_uint64_t >(0), __hip_uint64_t mask=static_cast< __hip_uint64_t >(0))
Definition amd_hip_cooperative_groups.h:52
unsigned int meta_group_size() const
Returns the number of groups created when the parent group was partitioned.
Definition amd_hip_cooperative_groups.h:486
unsigned int thread_rank() const
Rank of the calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:372
unsigned int thread_rank() const
Rank of the calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:472
unsigned int meta_group_size() const
Returns the number of groups created when the parent group was partitioned.
Definition amd_hip_cooperative_groups.h:996
int all(int pred) const
All function on group level.
Definition amd_hip_cooperative_groups.h:617
unsigned int cg_type() const
Returns the type of the group.
Definition amd_hip_cooperative_groups.h:86
T shfl(T var, int srcRank) const
Definition amd_hip_cooperative_groups.h:877
thread_group new_tiled_group(unsigned int tile_size) const
Definition amd_hip_cooperative_groups.h:255
static __hip_uint32_t size()
Total number of threads in the group (alias of num_threads())
Definition amd_hip_cooperative_groups.h:294
unsigned int num_threads() const
Definition amd_hip_cooperative_groups.h:364
unsigned int num_threads() const
Definition amd_hip_cooperative_groups.h:466
void barrier_wait(arrival_token &&) const
Arrive at a barrier.
Definition amd_hip_cooperative_groups.h:308
tiled_group(unsigned int tileSize)
Definition amd_hip_cooperative_groups.h:356
unsigned int meta_group_rank
Definition amd_hip_cooperative_groups.h:63
void sync() const
Synchronizes the threads in the group.
unsigned long long match_all(T value, int &pred) const
Match all function on group level.
Definition amd_hip_cooperative_groups.h:646
thread_block_tile_type()
Definition amd_hip_cooperative_groups.h:945
__hip_uint32_t block_rank() const
Rank of the block in calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:199
grid_group(__hip_uint32_t size)
Construct grid thread group (through the API this_grid())
Definition amd_hip_cooperative_groups.h:192
__hip_uint32_t grid_rank()
Definition amd_hip_cooperative_groups.h:147
static constexpr unsigned int thread_rank()
Rank of the thread within this tile.
Definition amd_hip_cooperative_groups.h:841
bool is_tiled
Definition amd_hip_cooperative_groups.h:61
unsigned long long ballot(int pred) const
Ballot function on group level.
Definition amd_hip_cooperative_groups.h:595
void sync() const
Synchronizes the threads in the group.
Definition amd_hip_cooperative_groups.h:155
T shfl_up(T var, unsigned int lane_delta) const
Definition amd_hip_cooperative_groups.h:885
static __hip_uint32_t block_rank()
Rank of the block in calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:286
static dim3 group_index()
Returns 3-dimensional block index within the grid.
Definition amd_hip_cooperative_groups.h:278
unsigned long long groupMask(const TyGroup &)
Definition amd_hip_cooperative_groups.h:1459
unsigned int num_threads
Definition amd_hip_cooperative_groups.h:69
static void sync()
Synchronizes the threads in the group.
Definition amd_hip_cooperative_groups.h:298
friend coalesced_group binary_partition(const thread_block_tile< fsize, fparent > &tgrp, bool pred)
__hip_uint32_t thread_rank() const
Rank of the calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:149
bool is_valid() const
Returns true if the group has not violated any API constraints.
static unsigned int size()
Definition amd_hip_cooperative_groups.h:850
friend thread_group tiled_partition(const thread_group &parent, unsigned int tile_size)
User-exposed API to partition groups.
Definition amd_hip_cooperative_groups.h:1017
int any(int pred) const
Definition amd_hip_cooperative_groups.h:899
int all(int pred) const
Definition amd_hip_cooperative_groups.h:901
__hip_uint64_t _mask
Total number of threads in the thread_group.
Definition amd_hip_cooperative_groups.h:45
friend thread_group this_thread()
Definition amd_hip_cooperative_groups.h:1005
bool is_valid() const
Returns true if the group has not violated any API constraints.
Definition amd_hip_cooperative_groups.h:201
__hip_uint32_t _type
Definition amd_hip_cooperative_groups.h:43
unsigned long long match_any(T value) const
Definition amd_hip_cooperative_groups.h:903
unsigned int size() const
Total number of threads in the group (alias of num_threads())
Definition amd_hip_cooperative_groups.h:369
struct cooperative_groups::thread_group::_coalesced_info coalesced_info
lane_mask member_mask
Definition amd_hip_cooperative_groups.h:68
thread_block(__hip_uint32_t size)
Definition amd_hip_cooperative_groups.h:252
unsigned int meta_group_size
Definition amd_hip_cooperative_groups.h:64
multi_grid_group(__hip_uint32_t size)
Construct multi-grid thread group (through the API this_multi_grid())
Definition amd_hip_cooperative_groups.h:137
int any(int pred) const
Any function on group level.
Definition amd_hip_cooperative_groups.h:607
thread_group this_thread()
Definition amd_hip_cooperative_groups.h:1005
cluster_group this_cluster()
get cluster group
Definition amd_hip_cooperative_groups.h:1605
static unsigned int meta_group_rank()
Definition amd_hip_cooperative_groups.h:921
__hip_uint32_t num_threads() const
Definition amd_hip_cooperative_groups.h:82
struct _tiled_info tiled_info
Definition amd_hip_cooperative_groups.h:70
friend coalesced_group coalesced_threads()
User-exposed API to create coalesced groups.
Definition amd_hip_cooperative_groups.h:663
friend coalesced_group binary_partition(const coalesced_group &cgrp, bool pred)
Binary partition.
Definition amd_hip_cooperative_groups.h:1298
static dim3 thread_index()
Returns 3-dimensional thread index within the block.
Definition amd_hip_cooperative_groups.h:280
friend class thread_block
Definition amd_hip_cooperative_groups.h:76
coalesced_group(lane_mask member_mask)
Definition amd_hip_cooperative_groups.h:454
T shfl_down(T var, unsigned int lane_delta) const
Shuffle down operation on group level.
Definition amd_hip_cooperative_groups.h:527
static bool is_valid()
Returns true if the group has not violated any API constraints.
Definition amd_hip_cooperative_groups.h:296
dim3 group_dim()
Returns the group dimensions.
Definition amd_hip_cooperative_groups.h:300
thread_block_tile_type(unsigned int meta_group_rank, unsigned int meta_group_size)
Definition amd_hip_cooperative_groups.h:974
static __hip_uint32_t num_threads()
Definition amd_hip_cooperative_groups.h:290
unsigned long long ballot(int pred) const
Definition amd_hip_cooperative_groups.h:894
T shfl(T var, int srcRank) const
Shuffle operation on group level.
Definition amd_hip_cooperative_groups.h:502
arrival_token barrier_arrive() const
Arrive at a barrier.
Definition amd_hip_cooperative_groups.h:303
bool is_valid() const
Returns true if the group has not violated any API constraints.
Definition amd_hip_cooperative_groups.h:153
static __hip_uint32_t thread_rank()
Rank of the calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:282
friend grid_group this_grid()
User-exposed API interface to construct grid cooperative group type object - grid_group.
Definition amd_hip_cooperative_groups.h:230
T shfl_down(T var, unsigned int lane_delta) const
Definition amd_hip_cooperative_groups.h:881
T shfl_up(T var, unsigned int lane_delta) const
Shuffle up operation on group level.
Definition amd_hip_cooperative_groups.h:564
thread_block_tile_type(unsigned int meta_group_rank, unsigned int meta_group_size)
Definition amd_hip_cooperative_groups.h:950
__hip_uint32_t thread_rank() const
Rank of the calling thread within [0, num_threads() ).
Definition amd_hip_cooperative_groups.h:205
Definition amd_hip_cooperative_groups.h:301
Definition amd_hip_cooperative_groups.h:67
Definition amd_hip_cooperative_groups.h:60
void bPermute(T &, T, int from)
Definition amd_hip_cooperative_groups.h:1480
__hip_internal::is_same< typename __hip_internal::remove_cvref< T >, typename __hip_internal::remove_cvref< U > > is_param_type_same
Definition amd_hip_cooperative_groups.h:1385
Definition amd_hip_cooperative_groups.h:1249
Definition amd_hip_cooperative_groups.h:24
Definition amd_hip_cooperative_groups.h:1357
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1358
Definition amd_hip_cooperative_groups.h:1373
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1374
Definition amd_hip_cooperative_groups.h:1365
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1366
Definition amd_hip_cooperative_groups.h:1349
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1350
T operator()()
Definition amd_hip_cooperative_groups.h:1431
T operator()()
Definition amd_hip_cooperative_groups.h:1450
T operator()()
Definition amd_hip_cooperative_groups.h:1440
Definition amd_hip_cooperative_groups.h:1421
T operator()()
Definition amd_hip_cooperative_groups.h:1422
Definition amd_hip_cooperative_groups.h:1388
Definition amd_hip_cooperative_groups.h:1404
Definition amd_hip_cooperative_groups.h:1082
Definition amd_hip_cooperative_groups.h:1061
tiled_partition_internal(const thread_block &g)
Definition amd_hip_cooperative_groups.h:1253
tiled_partition_internal(const thread_block_tile< ParentSize, GrandParentCGTy > &g)
Definition amd_hip_cooperative_groups.h:1263
Definition amd_hip_cooperative_groups.h:1073
Definition amd_hip_cooperative_groups.h:1341
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1342
Definition amd_hip_cooperative_groups.h:1333
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1334
Definition hip_runtime_api.h:1375