cuda::experimental::coop::this_{level}#
namespace cuda::experimental::coop {
template <typename Level, typename Hierarchy>
class /*this-group*/ : public /*group-interface-for*/</*this-group*/>
{
public:
using unit_type = Level;
using level_type = Level;
using hierarchy_type = Hierarchy;
/*this-group*/() = delete;
template <typename HierarchyLike>
requires cuda::std::same_as<Hierarchy, /*hierarchy-type-of*/<HierarchyLike>>
__device__ /*this-group*/(const HierarchyLike& hierarchy_like) noexcept;
/*this-group*/(const /*this-group*/&) = delete;
/*this-group*/(/*this-group*/&&) = delete;
/*this-group*/& operator=(const /*this-group*/&) = delete;
/*this-group*/& operator=(/*this-group*/&&) = delete;
};
template <typename Hierarchy>
class this_thread : public /*this-group*/<thread_level, Hierarchy> {};
template <typename Hierarchy>
class this_warp : public /*this-group*/<warp_level, Hierarchy> {};
template <typename Hierarchy>
class this_block : public /*this-group*/<block_level, Hierarchy> {};
template <typename Hierarchy>
class this_cluster : public /*this-group*/<cluster_level, Hierarchy> {};
template <typename Hierarchy>
class this_grid : public /*this-group*/<grid_level, Hierarchy> {};
template </*hierarchy-level-type*/ Level, /*hierarchy-like-type*/ HierarchyLike>
[[nodiscard]] __device__
auto make_this_group(const Level& level, const HierarchyLike& hierarchy_like) noexcept;
} // namespace cuda::experimental::coop
Overview#
This groups are the simplest groups that contain a single unit within the same level. They are the building blocks for all other groups. They are implemented by several classes named cuda::experimental::coop::this_{level} where level is any of the predefined CUDA levels. They can be explicitly constructed from a hierarchy-like object.
Because every this group is a separate type, the cuda::experimental::coop::make_this_group(...) factory function is provided to construct any this group based on the parameters.
This groups are always contiguous.
This groups use the cuda::experimental::coop::level_synchronizer synchronizer for synchronization.
Queries#
Sub-unit queries work as with any other group type; however, since this groups don’t have a parent group, a native hierarchy level must be used in the super-level queries as the upper bound. For example, cuda::experimental::coop::this_warp{...}.count(cuda::block) queries the number of warps within a block.
Examples#
#include <cuda/devices>
#include <cuda/stream>
#include <cuda/hierarchy>
#include <cuda/launch>
#include <cuda/std/cstdint>
#include <cuda/std/cassert>
#include <cuda/experimental/coop/group>
#include <cstdio>
namespace cudax = cuda::experimental;
__device__ void print_info(auto group, const char* group_name)
{
// Query thread and group information.
const auto thread_count = cuda::gpu_thread.count_as<cuda::std::uint32_t>(group);
const auto thread_rank = cuda::gpu_thread.rank_as<cuda::std::uint32_t>(group);
const auto group_count = group.template count_as<cuda::std::uint32_t>(cuda::grid);
const auto group_rank = group.template rank_as<cuda::std::uint32_t>(cuda::grid);
// When the launch dimensions are known at compile time, the static_count query returns a valid count;
// otherwise, cuda::std::dynamic_extent is returned.
constexpr auto static_thread_count = cuda::gpu_thread.static_count(group);
constexpr auto static_group_count = group.static_count(cuda::grid);
if (thread_rank == 0 && group_rank == 0)
{
printf("%s contains %u threads%s. There are %u groups within the grid%s.\n",
group_name,
thread_count,
(static_thread_count != cuda::std::dynamic_extent) ? " (statically known)" : "",
group_count,
(static_group_count != cuda::std::dynamic_extent) ? " (statically known)" : "");
}
// Ranks are always in the range `[0;count)`.
assert(thread_rank < thread_count);
assert(group_rank < group_count);
// The .sync() method synchronizes the whole group. Synchronizing this_grid requires a cooperative launch.
group.sync();
}
struct Kernel
{
__device__ void operator()(auto config) const
{
print_info(cudax::coop::this_thread{config}, "this_thread");
print_info(cudax::coop::this_warp{config}, "this_warp");
print_info(cudax::coop::this_block{config}, "this_block");
print_info(cudax::coop::this_cluster{config}, "this_cluster");
print_info(cudax::coop::this_grid{config}, "this_grid");
}
};
int main()
{
// Select a device and create a stream for it.
const auto device = cuda::devices[0];
cuda::stream stream{device};
// Launch the test kernel on the stream. Use the cooperative launch tag to make sure we can synchronize the whole grid.
const auto config = cuda::make_config(cuda::grid_dims(2), cuda::block_dims<128>(), cuda::cooperative_launch{});
cuda::launch(stream, config, Kernel{});
// Wait until the kernel finishes.
stream.sync();
}