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}
762
763#endif
764
782template <class CGTy> __CG_QUALIFIER__ __hip_uint32_t group_size(CGTy const& g) {
783 return g.num_threads();
784}
785
797template <class CGTy> __CG_QUALIFIER__ __hip_uint32_t thread_rank(CGTy const& g) {
798 return g.thread_rank();
799}
800
810template <class CGTy> __CG_QUALIFIER__ bool is_valid(CGTy const& g) { return g.is_valid(); }
811
821template <class CGTy> __CG_QUALIFIER__ void sync(CGTy const& g) { g.sync(); }
822
823// Doxygen end group CooperativeGAPI
831template <unsigned int tileSize> class tile_base {
832 protected:
833 _CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
834
835 public:
837 _CG_STATIC_CONST_DECL_ unsigned int thread_rank() {
838 return (internal::workgroup::thread_rank() & (numThreads - 1));
839 }
840
842 __CG_STATIC_QUALIFIER__ unsigned int num_threads() { return numThreads; }
843
846 __CG_STATIC_QUALIFIER__ unsigned int size() { return num_threads(); }
847};
848
854template <unsigned int size> class thread_block_tile_base : public tile_base<size> {
855 static_assert(is_valid_tile_size<size>::value,
856 "Tile size is either not a power of 2 or greater than the wavefront size");
858
859 template <unsigned int fsize, class fparent> friend __CG_QUALIFIER__ coalesced_group
861
862#if !defined(HIP_DISABLE_WARP_SYNC_BUILTINS)
863 __CG_QUALIFIER__ unsigned long long build_mask() const {
864 unsigned long long mask = ~0ull >> (64 - numThreads);
865 // thread_rank() gives thread id from 0..thread launch size.
866 return mask << (((internal::workgroup::thread_rank() % warpSize) / numThreads) * numThreads);
867 }
868#endif // HIP_DISABLE_WARP_SYNC_BUILTINS
869
870 public:
871 __CG_STATIC_QUALIFIER__ void sync() { internal::tiled_group::sync(); }
872
873 template <class T> __CG_QUALIFIER__ T shfl(T var, int srcRank) const {
874 return (__shfl(var, srcRank, numThreads));
875 }
876
877 template <class T> __CG_QUALIFIER__ T shfl_down(T var, unsigned int lane_delta) const {
878 return (__shfl_down(var, lane_delta, numThreads));
879 }
880
881 template <class T> __CG_QUALIFIER__ T shfl_up(T var, unsigned int lane_delta) const {
882 return (__shfl_up(var, lane_delta, numThreads));
883 }
884
885 template <class T> __CG_QUALIFIER__ T shfl_xor(T var, unsigned int laneMask) const {
886 return (__shfl_xor(var, laneMask, numThreads));
887 }
888
889#if !defined(HIP_DISABLE_WARP_SYNC_BUILTINS)
890 __CG_QUALIFIER__ unsigned long long ballot(int pred) const {
891 const auto mask = build_mask();
892 return internal::helper::adjust_mask(mask, __ballot_sync(mask, pred));
893 }
894
895 __CG_QUALIFIER__ int any(int pred) const { return __any_sync(build_mask(), pred); }
896
897 __CG_QUALIFIER__ int all(int pred) const { return __all_sync(build_mask(), pred); }
898
899 template <typename T> __CG_QUALIFIER__ unsigned long long match_any(T value) const {
900 const auto mask = build_mask();
901 return internal::helper::adjust_mask(mask, __match_any_sync(mask, value));
902 }
903
904 template <typename T> __CG_QUALIFIER__ unsigned long long match_all(T value, int& pred) const {
905 const auto mask = build_mask();
906 return internal::helper::adjust_mask(mask, __match_all_sync(mask, value, &pred));
907 }
908#endif // HIP_DISABLE_WARP_SYNC_BUILTINS
909};
910
913template <unsigned int tileSize, typename ParentCGTy> class parent_group_info {
914 public:
917 __CG_STATIC_QUALIFIER__ unsigned int meta_group_rank() {
918 const unsigned int rank = ParentCGTy::thread_rank() / tileSize;
919#if defined(__HIP_DEVICE_COMPILE__) && defined(__AMDGCN__)
920 if (tileSize % warpSize == 0) {
921 return __builtin_amdgcn_is_invocable(__builtin_amdgcn_readfirstlane)
922 ? __builtin_amdgcn_readfirstlane(rank)
923 : rank;
924 }
925#endif
926 return rank;
927 }
928
930 __CG_STATIC_QUALIFIER__ unsigned int meta_group_size() {
931 return (ParentCGTy::num_threads() + tileSize - 1) / tileSize;
932 }
933};
934
941template <unsigned int tileSize, class ParentCGTy> class thread_block_tile_type
942 : public thread_block_tile_base<tileSize>,
943 public tiled_group,
944 public parent_group_info<tileSize, ParentCGTy> {
945 _CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
947
948 protected:
949 __CG_QUALIFIER__ thread_block_tile_type() : tiled_group(numThreads) {
952 }
953
962
963 public:
965 using tbtBase::size;
968};
969
970// Partial template specialization
971template <unsigned int tileSize> class thread_block_tile_type<tileSize, void>
972 : public thread_block_tile_base<tileSize>, public tiled_group {
973 _CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
974
976
977 protected:
986
987 public:
989 using tbtBase::size;
990 using tbtBase::sync;
992
995 __CG_QUALIFIER__ unsigned int meta_group_rank() const {
997 }
998
1000 __CG_QUALIFIER__ unsigned int meta_group_size() const {
1002 }
1003 // Doxygen end group CooperativeG
1007};
1008
1009__CG_QUALIFIER__ thread_group this_thread() {
1010 thread_group g(internal::group_type::cg_coalesced_group, 1, __ockl_activelane_u32());
1011 return g;
1012}
1013
1021__CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent, unsigned int tile_size) {
1022 if (parent.cg_type() == internal::cg_tiled_group) {
1023 const tiled_group* cg = static_cast<const tiled_group*>(&parent);
1024 return cg->new_tiled_group(tile_size);
1025 } else if (parent.cg_type() == internal::cg_coalesced_group) {
1026 const coalesced_group* cg = static_cast<const coalesced_group*>(&parent);
1027 return cg->new_tiled_group(tile_size);
1028 } else {
1029 const thread_block* tb = static_cast<const thread_block*>(&parent);
1030 return tb->new_tiled_group(tile_size);
1031 }
1032}
1033
1034// Thread block type overload
1035__CG_QUALIFIER__ thread_group tiled_partition(const thread_block& parent, unsigned int tile_size) {
1036 return (parent.new_tiled_group(tile_size));
1037}
1038
1039__CG_QUALIFIER__ tiled_group tiled_partition(const tiled_group& parent, unsigned int tile_size) {
1040 return (parent.new_tiled_group(tile_size));
1041}
1042
1043// If a coalesced group is passed to be partitioned, it should remain coalesced
1044__CG_QUALIFIER__ coalesced_group tiled_partition(const coalesced_group& parent,
1045 unsigned int tile_size) {
1046 return (parent.new_tiled_group(tile_size));
1047}
1048
1049namespace impl {
1050template <unsigned int size, class ParentCGTy> class thread_block_tile_internal;
1051
1052template <unsigned int size, class ParentCGTy> class thread_block_tile_internal
1053 : public thread_block_tile_type<size, ParentCGTy> {
1054 protected:
1055 template <unsigned int tbtSize, class tbtParentT> __CG_QUALIFIER__ thread_block_tile_internal(
1058
1059 __CG_QUALIFIER__ thread_block_tile_internal(const thread_block& g)
1060 : thread_block_tile_type<size, ParentCGTy>() {}
1061};
1062
1063// becomes to std::true_type if the group is tiled and has a size known at compile time
1064template <class TyGroup>
1065struct isTiledGroup : __hip_internal::false_type {
1066};
1067
1068template <unsigned int N, class ParentCGTy>
1070 : __hip_internal::integral_constant<bool,
1071 (N == 1 || N == 2 || N == 4 || N == 8 ||
1072 N == 16 || N == 32 || N == 64)> {
1073};
1074
1075// returns the size of tile_group provided it is known at compile time
1076template <class TyGroup>
1077struct tiledGroupSize : __hip_internal::integral_constant<int, 0> {
1078
1079};
1080template <unsigned int N, class ParentCGTy>
1082 : __hip_internal::integral_constant<int, N> {
1083};
1084
1085template <class TyGroup>
1086struct isCoalescedGroup : __hip_internal::false_type {
1087};
1088
1089template <>
1090struct isCoalescedGroup<cooperative_groups::coalesced_group> : __hip_internal::true_type {
1091};
1092} // namespace impl
1093
1102template <unsigned int size, class ParentCGTy> class thread_block_tile
1103 : public impl::thread_block_tile_internal<size, ParentCGTy> {
1104 protected:
1105 __CG_QUALIFIER__ thread_block_tile(const ParentCGTy& g)
1106 : impl::thread_block_tile_internal<size, ParentCGTy>(g) {}
1107
1108 public:
1109 __CG_QUALIFIER__ operator thread_block_tile<size, void>() const {
1110 return thread_block_tile<size, void>(*this);
1111 }
1112
1113#ifdef DOXYGEN_SHOULD_INCLUDE_THIS
1114
1116 __CG_QUALIFIER__ unsigned int thread_rank() const;
1117
1119 __CG_QUALIFIER__ void sync();
1120
1123 __CG_QUALIFIER__ unsigned int meta_group_rank() const;
1124
1126 __CG_QUALIFIER__ unsigned int meta_group_size() const;
1127
1140 template <class T> __CG_QUALIFIER__ T shfl(T var, int srcRank) const;
1141
1156 template <class T> __CG_QUALIFIER__ T shfl_down(T var, unsigned int lane_delta) const;
1157
1172 template <class T> __CG_QUALIFIER__ T shfl_up(T var, unsigned int lane_delta) const;
1173
1186 template <class T> __CG_QUALIFIER__ T shfl_xor(T var, unsigned int laneMask) const;
1187
1195 __CG_QUALIFIER__ unsigned long long ballot(int pred) const;
1196
1203 __CG_QUALIFIER__ int any(int pred) const;
1204
1211 __CG_QUALIFIER__ int all(int pred) const;
1212
1221 template <typename T> __CG_QUALIFIER__ unsigned long long match_any(T value) const;
1222
1234 template <typename T> __CG_QUALIFIER__ unsigned long long match_all(T value, int& pred) const;
1235
1236#endif
1237};
1238
1239template <unsigned int size> class thread_block_tile<size, void>
1240 : public impl::thread_block_tile_internal<size, void> {
1241 template <unsigned int, class ParentCGTy> friend class thread_block_tile;
1242
1243 protected:
1244 public:
1245 template <class ParentCGTy>
1247 : impl::thread_block_tile_internal<size, void>(g) {}
1248};
1249
1250template <unsigned int size, class ParentCGTy = void> class thread_block_tile;
1251
1252namespace impl {
1253template <unsigned int size, class ParentCGTy> struct tiled_partition_internal;
1254
1255template <unsigned int size> struct tiled_partition_internal<size, thread_block>
1256 : public thread_block_tile<size, thread_block> {
1259};
1260
1261// ParentCGTy = thread_block_tile<ParentSize, GrandParentCGTy> specialization
1262template <unsigned int size, unsigned int ParentSize, class GrandParentCGTy>
1263struct tiled_partition_internal<size, thread_block_tile<ParentSize, GrandParentCGTy> >
1264 : public thread_block_tile<size, thread_block_tile<ParentSize, GrandParentCGTy> > {
1265 static_assert(size < ParentSize, "Sub tile size must be < parent tile size in tiled_partition");
1266
1268 : thread_block_tile<size, thread_block_tile<ParentSize, GrandParentCGTy> >(g) {}
1269};
1270
1271} // namespace impl
1272
1285template <unsigned int size, class ParentCGTy>
1286__CG_QUALIFIER__ thread_block_tile<size, ParentCGTy> tiled_partition(const ParentCGTy& g) {
1287 static_assert(is_valid_tile_size<size>::value,
1288 "Tiled partition with size > wavefront size. Currently not supported ");
1290}
1291
1292namespace impl {
1293
1294template <typename T>
1295__CG_QUALIFIER__ T&& forward(typename __hip_internal::remove_reference<T>::type& t) {
1296 return static_cast<T&&>(t);
1297}
1298
1299template <typename T>
1300__CG_QUALIFIER__ T&& forward(typename __hip_internal::remove_reference<T>::type&& t) {
1301 return static_cast<T&&>(t);
1302}
1303
1304} // namespace impl
1305
1322template <typename Group, typename Fn, typename... Args>
1323__CG_QUALIFIER__ void invoke_one(const Group& g, Fn&& fn, Args&&... args) {
1324 if (g.thread_rank() == 0) {
1326 }
1327}
1328
1329namespace impl {
1330
1331template <typename Group, typename Fn, typename... Args>
1333 typename __hip_internal::remove_reference<decltype(impl::forward<Fn>(fn)(
1334 impl::forward<Args>(args)...))>::type {
1335 using ResultType = typename __hip_internal::remove_cvref<decltype(impl::forward<Fn>(fn)(
1336 impl::forward<Args>(args)...))>::type;
1337 static_assert(__hip_internal::is_trivially_copyable<ResultType>::value,
1338 "The return type of the invocable must be trivially copyable");
1339 static_assert(sizeof(ResultType) <= 32,
1340 "The return type of the invocable must be at most 32 bytes");
1341
1342 // The result is moved one 32-bit word at a time.
1343 constexpr unsigned int num_words =
1344 (sizeof(ResultType) + sizeof(unsigned int) - 1) / sizeof(unsigned int);
1345
1346 struct ResultBytes {
1347 unsigned char data[sizeof(ResultType)];
1348 };
1349
1350 unsigned int words[num_words] = {};
1351 if (g.thread_rank() == 0) {
1355 }
1356
1357 for (unsigned int i = 0; i < num_words; ++i) {
1358 words[i] = g.shfl(words[i], 0);
1359 }
1360
1364}
1365
1366} // namespace impl
1367
1384template <typename Fn, typename... Args>
1385__CG_QUALIFIER__ auto invoke_one_broadcast(const coalesced_group& g, Fn&& fn, Args&&... args) ->
1386 typename __hip_internal::remove_reference<decltype(impl::forward<Fn>(fn)(
1387 impl::forward<Args>(args)...))>::type {
1388 using ResultType = decltype(impl::forward<Fn>(fn)(impl::forward<Args>(args)...));
1389 static_assert(!__hip_internal::is_void<ResultType>::value,
1390 "For invocables returning void invoke_one should be used instead");
1392}
1393
1412template <unsigned int Size, typename Parent, typename Fn, typename... Args>
1413__CG_QUALIFIER__ auto invoke_one_broadcast(const thread_block_tile<Size, Parent>& g, Fn&& fn,
1414 Args&&... args) ->
1415 typename __hip_internal::remove_reference<decltype(impl::forward<Fn>(fn)(
1416 impl::forward<Args>(args)...))>::type {
1417 using ResultType = decltype(impl::forward<Fn>(fn)(impl::forward<Args>(args)...));
1418 static_assert(!__hip_internal::is_void<ResultType>::value,
1419 "For invocables returning void invoke_one should be used instead");
1421}
1422
1423#if !defined(HIP_DISABLE_WARP_SYNC_BUILTINS)
1424
1433__CG_QUALIFIER__ coalesced_group binary_partition(const coalesced_group& cgrp, bool pred) {
1434 auto mask = __ballot_sync<unsigned long long>(cgrp.coalesced_info.member_mask, pred);
1435
1436 if (pred) {
1437 return coalesced_group(mask);
1438 } else {
1439 return coalesced_group(cgrp.coalesced_info.member_mask ^ mask);
1440 }
1441}
1442
1454template <unsigned int size, class parent>
1456 bool pred) {
1457 auto mask = __ballot_sync<unsigned long long>(tgrp.build_mask(), pred);
1458
1459 if (pred) {
1460 return coalesced_group(mask);
1461 } else {
1462 return coalesced_group(tgrp.build_mask() ^ mask);
1463 }
1464}
1465
1466
1467template <class T>
1468struct plus {
1469 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1470 {
1471 return lhs + rhs;
1472 }
1473};
1474
1475template <class T>
1476struct less {
1477 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1478 {
1479 return lhs < rhs? lhs : rhs;
1480 }
1481};
1482
1483template <class T>
1484struct greater {
1485 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1486 {
1487 return lhs < rhs? rhs : lhs;
1488 }
1489};
1490
1491template <class T>
1492struct bit_and {
1493 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1494 {
1495 return lhs & rhs;
1496 }
1497};
1498
1499template <class T>
1500struct bit_xor {
1501 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1502 {
1503 return lhs ^ rhs;
1504 }
1505};
1506
1507template <class T>
1508struct bit_or {
1509 __CG_QUALIFIER__ T operator()(T lhs, T rhs) const
1510 {
1511 return lhs | rhs;
1512 }
1513};
1514
1515namespace impl {
1516// when instantiated with two parameter types, allows to know if there are the same, regardless
1517// of const/volatile qualifiers
1518template <typename T, typename U>
1519using is_param_type_same = __hip_internal::is_same<typename __hip_internal::remove_cvref<T>,
1520 typename __hip_internal::remove_cvref<U>>;
1521
1522template <class T, class Op>
1523struct isArithmeticFunc : __hip_internal::false_type {
1524};
1525
1526template <class T>
1527struct isArithmeticFunc<T, cooperative_groups::plus<T>> : __hip_internal::true_type {
1528};
1529
1530template <class T>
1531struct isArithmeticFunc<T, cooperative_groups::less<T>> : __hip_internal::true_type {
1532};
1533
1534template <class T>
1535struct isArithmeticFunc<T, cooperative_groups::greater<T>> : __hip_internal::true_type {
1536};
1537
1538template <class T, class Op>
1539struct isBooleanFunc : __hip_internal::false_type {
1540};
1541
1542template <class T>
1543struct isBooleanFunc<T, cooperative_groups::bit_and<T>> : __hip_internal::true_type {
1544};
1545
1546template <class T>
1547struct isBooleanFunc<T, cooperative_groups::bit_or<T>> : __hip_internal::true_type {
1548};
1549
1550template <class T>
1551struct isBooleanFunc<T, cooperative_groups::bit_xor<T>> : __hip_internal::true_type {
1552};
1553
1554// this is the value to return in exclusive_scan, for lane 0
1555template <class T, class Op>
1558 {
1559 T result = {};
1560 return result;
1561 }
1562};
1563
1564template <class T>
1567 {
1568 T result {};
1569 return ~result;
1570 }
1571};
1572
1573template <>
1576 {
1577 return true;
1578 }
1579};
1580
1581template <>
1584 {
1585 return false;
1586 }
1587};
1588
1589template <class T>
1592 {
1593 // CUDA would return 0 in this case. But in our case we mimic what __ockl_wfscan_*
1594 // would do
1595 return __hip_internal::ExclusiveScanIdentity<T>::maximum();
1596 }
1597};
1598
1599template <>
1602 {
1603 return true;
1604 }
1605};
1606
1607template <class T>
1610 {
1611 return __hip_internal::ExclusiveScanIdentity<T>::minimum();
1612 }
1613};
1614
1615template <>
1618 {
1619 return false;
1620 }
1621};
1622
1623// calculates the necessary warp mask for cooperative groups that support reduce(), or
1624// inclusive/exlcusive_scan()
1625template <typename TyGroup>
1626__CG_QUALIFIER__ unsigned long long groupMask(const TyGroup& group)
1627{
1628 unsigned long long mask = ~0ull;
1629
1631 mask = group.coalesced_info.member_mask;
1632 } else {
1633 // we cannot simply just use the __activemask() here, because more than one tile could have active
1634 // threads at a time; we need to mask away the threads that not part of this tile first
1635 mask >>= (64 - group.num_threads());
1636 mask <<= (((internal::workgroup::thread_rank() % warpSize) / group.num_threads()) * group.num_threads());
1637 }
1638
1639 return mask;
1640}
1641
1642// backward permute implementation for cooperative group operations, i.e.
1643// for up to 32 bytes (__hip_ds_bpermute() can only do 4 bytes at a time,
1644// this function calls it (or the floating point version) multiple times to
1645// implement it for bigger sizes
1646template <bool isPrimitiveType, class T, size_t NumPermutes,
1647 typename __hip_internal::enable_if<NumPermutes == 0, int>::type = 0>
1649{
1650}
1651
1652// trivial case: the type fits within the permute size
1653template <bool IsPrimitiveType, class T, size_t NumPermutes,
1654 typename __hip_internal::enable_if<IsPrimitiveType && NumPermutes == 1, int>::type = 0>
1655__CG_QUALIFIER__ void bPermute(T& permuteResult, T result, int from)
1656{
1657 auto backwardPermute = [](int index, T arg) {
1658 if constexpr (__hip_internal::is_floating_point<T>::value &&
1659 sizeof(T) <= 4) {
1660 return __hip_ds_bpermutef(index, arg);
1661 } else {
1662 return __hip_ds_bpermute(index, arg);
1663 }
1664 };
1665
1666 if constexpr (sizeof(T) <= 2) {
1667 union {
1668 int i;
1669 T f;
1670 } tmp = {};
1671
1672 tmp.f = result;
1673 tmp.i = __hip_ds_bpermute(from << 2, tmp.i);
1674 permuteResult = tmp.f;
1675 } else if constexpr (sizeof(T) == 4) {
1676 auto bPermuteResult = backwardPermute(from << 2, result);
1677 __builtin_memcpy(&permuteResult, &bPermuteResult, sizeof(result));
1678 } else {
1679 static_assert(__hip_internal::is_void<T>::value, "Unexpected type");
1680 }
1681}
1682
1683// Overload when we need multiple ds_permute, because one is not enough
1684template <bool IsPrimitiveType, class T, size_t NumPermutes>
1686{
1687 // ds_bpermute only deals with 32-bit sizes, so for other sizes
1688 // we need to call the permute multiple times
1689 for (int i = 0; i < NumPermutes; i++) {
1691 }
1692}
1693
1694} // namespace impl
1695#endif
1696
1704 friend __CG_QUALIFIER__ cluster_group this_cluster();
1705
1706 // Default constructor, hidden
1707 __CG_QUALIFIER__ cluster_group() {}
1708
1709 public:
1710 using arrival_token = struct {};
1711
1712 // Sync the cluster, equivalent to c.barrier_wait(c.barrier_arrive());
1713 __CG_STATIC_QUALIFIER__ void sync() { internal::cluster::sync(); }
1714
1715 // Arrive on a cluster barrier, returns token that needs to be passed to barrier_wait
1716 __CG_STATIC_QUALIFIER__ arrival_token barrier_arrive() {
1717 // signal user cluster barrier
1718 internal::cluster::barrier_arrive();
1719 return arrival_token();
1720 }
1721
1722 // Wait on arrival_token
1723 __CG_STATIC_QUALIFIER__ void barrier_wait(arrival_token&&) { internal::cluster::barrier_wait(); }
1724
1725 // TODO: implement this when compiler work is done
1726 // block rank to which shared memory address belongs to
1727 // __CG_STATIC_QUALIFIER__ unsigned int query_shared_rank(const void* addr) {}
1728 // Obtain the address of shared memory variable of another block in the cluster
1729 // template <typename T> __CG_STATIC_QUALIFIER__ T* map_shared_rank(T* addr, int rank) {}
1730
1731 // index of the calling block within cluster
1732 __CG_STATIC_QUALIFIER__ dim3 block_index() { return internal::cluster::block_index(); }
1733
1734 // Rank of calling block within [0, num_blocks)
1735 __CG_STATIC_QUALIFIER__ unsigned int block_rank() { return internal::cluster::block_rank(); }
1736
1737 // index of the calling thread within cluster
1738 __CG_STATIC_QUALIFIER__ dim3 thread_index() { return internal::cluster::thread_index(); }
1739
1740 // Rank of calling thread within [0, num_threads)
1741 __CG_STATIC_QUALIFIER__ unsigned int thread_rank() { return internal::cluster::thread_rank(); }
1742
1743 // Dimensions of launched cluster in unit of blocks
1744 __CG_STATIC_QUALIFIER__ dim3 dim_blocks() { return internal::cluster::dim_blocks(); }
1745
1746 // total number of blocks in the group
1747 __CG_STATIC_QUALIFIER__ unsigned int num_blocks() { return internal::cluster::num_blocks(); }
1748
1749 // Dimensions of launched cluster in unit of threads
1750 __CG_STATIC_QUALIFIER__ dim3 dim_threads() { return internal::cluster::dim_threads(); }
1751
1752 // Total number of threads in the group
1753 __CG_STATIC_QUALIFIER__ unsigned int num_threads() { return internal::cluster::num_threads(); }
1754
1755 // Get address of shared memory variable in another cluster
1756 template <typename T> __CG_STATIC_QUALIFIER__ T* map_shared_rank(T* in, int rank) {
1757 return internal::cluster::map_shared_rank<T>(in, rank);
1758 }
1759
1760 // Return block rank of shared memory address
1761 __CG_STATIC_QUALIFIER__ unsigned int query_shared_rank(const void* in) {
1762 return internal::cluster::query_shared_rank(in);
1763 }
1764
1765 // Alias of num_threads
1766 __CG_STATIC_QUALIFIER__ unsigned int size() { return num_threads(); }
1767};
1768
1774__CG_QUALIFIER__ cluster_group this_cluster() {
1775 cluster_group cg;
1776 return cg;
1777}
1778} // namespace cooperative_groups
1779
1780#endif // __cplusplus
1781#endif // HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_H
Cluster group.
Definition amd_hip_cooperative_groups.h:1703
static unsigned int query_shared_rank(const void *in)
Definition amd_hip_cooperative_groups.h:1761
static unsigned int thread_rank()
Definition amd_hip_cooperative_groups.h:1741
static dim3 thread_index()
Definition amd_hip_cooperative_groups.h:1738
static T * map_shared_rank(T *in, int rank)
Definition amd_hip_cooperative_groups.h:1756
static void sync()
Definition amd_hip_cooperative_groups.h:1713
{} arrival_token
Definition amd_hip_cooperative_groups.h:1710
static dim3 block_index()
Definition amd_hip_cooperative_groups.h:1732
static void barrier_wait(arrival_token &&)
Definition amd_hip_cooperative_groups.h:1723
static unsigned int block_rank()
Definition amd_hip_cooperative_groups.h:1735
static unsigned int num_threads()
Definition amd_hip_cooperative_groups.h:1753
static unsigned int size()
Definition amd_hip_cooperative_groups.h:1766
static arrival_token barrier_arrive()
Definition amd_hip_cooperative_groups.h:1716
static unsigned int num_blocks()
Definition amd_hip_cooperative_groups.h:1747
friend cluster_group this_cluster()
get cluster group
Definition amd_hip_cooperative_groups.h:1774
static dim3 dim_threads()
Definition amd_hip_cooperative_groups.h:1750
static dim3 dim_blocks()
Definition amd_hip_cooperative_groups.h:1744
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:1053
thread_block_tile_internal(const thread_block &g)
Definition amd_hip_cooperative_groups.h:1059
thread_block_tile_internal(const thread_block_tile_internal< tbtSize, tbtParentT > &g)
Definition amd_hip_cooperative_groups.h:1055
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:913
thread_block_tile(const thread_block_tile< size, ParentCGTy > &g)
Definition amd_hip_cooperative_groups.h:1246
Definition amd_hip_cooperative_groups.h:854
Group type - thread_block_tile.
Definition amd_hip_cooperative_groups.h:944
Group type - thread_block_tile.
Definition amd_hip_cooperative_groups.h:1103
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:1105
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:831
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:11063
auto invoke_one_broadcast(const coalesced_group &g, Fn &&fn, Args &&... args) -> typename __hip_internal::remove_reference< decltype(impl::forward< Fn >(fn)(impl::forward< Args >(args)...))>::type
Calls an invocable on a single thread of the group and broadcasts the result.
Definition amd_hip_cooperative_groups.h:1385
bool is_valid(CGTy const &g)
Returns true if the group has not violated any API constraints.
Definition amd_hip_cooperative_groups.h:810
void invoke_one(const Group &g, Fn &&fn, Args &&... args)
Calls an invocable on a single thread of the group.
Definition amd_hip_cooperative_groups.h:1323
void sync(CGTy const &g)
Synchronizes the threads in the group.
Definition amd_hip_cooperative_groups.h:821
__hip_uint32_t group_size(CGTy const &g)
Returns the size of the group.
Definition amd_hip_cooperative_groups.h:782
__hip_uint32_t thread_rank(CGTy const &g)
Returns the rank of thread of the group.
Definition amd_hip_cooperative_groups.h:797
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:1433
thread_group tiled_partition(const thread_group &parent, unsigned int tile_size)
User-exposed API to partition groups.
Definition amd_hip_cooperative_groups.h:1021
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:885
static constexpr unsigned int numThreads
Definition amd_hip_cooperative_groups.h:833
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:871
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:904
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:930
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:995
__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:842
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:1000
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:873
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:949
__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:837
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:881
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:1626
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:846
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:1021
int any(int pred) const
Definition amd_hip_cooperative_groups.h:895
int all(int pred) const
Definition amd_hip_cooperative_groups.h:897
__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:1009
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:899
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:1009
cluster_group this_cluster()
get cluster group
Definition amd_hip_cooperative_groups.h:1774
static unsigned int meta_group_rank()
Definition amd_hip_cooperative_groups.h:917
__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:1433
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:978
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:890
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:877
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:954
__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
T && forward(typename __hip_internal::remove_reference< T >::type &t)
Definition amd_hip_cooperative_groups.h:1295
void bPermute(T &, T, int from)
Definition amd_hip_cooperative_groups.h:1648
__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:1520
auto invoke_one_broadcast_impl(const Group &g, Fn &&fn, Args &&... args) -> typename __hip_internal::remove_reference< decltype(impl::forward< Fn >(fn)(impl::forward< Args >(args)...))>::type
Definition amd_hip_cooperative_groups.h:1332
Definition amd_hip_cooperative_groups.h:1253
Definition amd_hip_cooperative_groups.h:24
Definition amd_hip_cooperative_groups.h:1492
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1493
Definition amd_hip_cooperative_groups.h:1508
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1509
Definition amd_hip_cooperative_groups.h:1500
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1501
Definition amd_hip_cooperative_groups.h:1484
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1485
T operator()()
Definition amd_hip_cooperative_groups.h:1566
T operator()()
Definition amd_hip_cooperative_groups.h:1609
T operator()()
Definition amd_hip_cooperative_groups.h:1591
bool operator()()
Definition amd_hip_cooperative_groups.h:1601
Definition amd_hip_cooperative_groups.h:1556
T operator()()
Definition amd_hip_cooperative_groups.h:1557
Definition amd_hip_cooperative_groups.h:1523
Definition amd_hip_cooperative_groups.h:1539
Definition amd_hip_cooperative_groups.h:1086
Definition amd_hip_cooperative_groups.h:1065
tiled_partition_internal(const thread_block &g)
Definition amd_hip_cooperative_groups.h:1257
tiled_partition_internal(const thread_block_tile< ParentSize, GrandParentCGTy > &g)
Definition amd_hip_cooperative_groups.h:1267
Definition amd_hip_cooperative_groups.h:1077
Definition amd_hip_cooperative_groups.h:1476
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1477
Definition amd_hip_cooperative_groups.h:1468
T operator()(T lhs, T rhs) const
Definition amd_hip_cooperative_groups.h:1469
Definition hip_runtime_api.h:1451