| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This file contains the declaration of the SYCL 2020 group class. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef _LIBSYCL___IMPL_GROUP_HPP |
| #define _LIBSYCL___IMPL_GROUP_HPP |
| |
| #include <sycl/__impl/detail/config.hpp> |
| #include <sycl/__impl/detail/linearization.hpp> |
| #include <sycl/__impl/index_space_classes.hpp> |
| #include <sycl/__impl/memory_enums.hpp> |
| #include <sycl/__spirv/spirv_vars.hpp> |
| |
| #include <cstddef> |
| |
| _LIBSYCL_BEGIN_NAMESPACE_SYCL |
| |
| template <int> class nd_item; |
| |
| // SYCL2020 4.9.1.7. group class. |
| /// The group class encapsulates all functionality required to represent a |
| /// particular work-group within a parallel execution. |
| template <int Dimensions = 1> class group { |
| public: |
| using id_type = id<Dimensions>; |
| using range_type = range<Dimensions>; |
| using linear_id_type = std::size_t; |
| static constexpr int dimensions = Dimensions; |
| static constexpr memory_scope fence_scope = memory_scope::work_group; |
| |
| group(const group &rhs) = default; |
| group(group &&rhs) = default; |
| group &operator=(const group &rhs) = default; |
| group &operator=(group &&rhs) = default; |
| |
| /// \return an id representing the index of the work-group within the global |
| /// nd-range for every dimension. |
| id<Dimensions> get_group_id() const noexcept { |
| return __spirv::initBuiltInWorkgroupId<Dimensions, id<Dimensions>>(); |
| } |
| |
| /// Equivalent to `return get_group_id()[dimension]`. |
| std::size_t get_group_id(int dimension) const noexcept { |
| return get_group_id()[dimension]; |
| } |
| |
| /// \return a SYCL id representing the calling work-item’s position within the |
| /// work-group. |
| id<Dimensions> get_local_id() const noexcept { |
| return __spirv::initBuiltInLocalInvocationId<Dimensions, id<Dimensions>>(); |
| } |
| |
| /// Equivalent to `return get_local_id()[dimension]`. |
| std::size_t get_local_id(int dimension) const noexcept { |
| return get_local_id()[dimension]; |
| } |
| |
| /// \return a SYCL range representing all dimensions of the local range. |
| range<Dimensions> get_local_range() const noexcept { |
| return __spirv::initBuiltInWorkgroupSize<Dimensions, range<Dimensions>>(); |
| } |
| |
| /// Equivalent to `return get_local_range()[dimension]`. |
| std::size_t get_local_range(int dimension) const noexcept { |
| return get_local_range()[dimension]; |
| } |
| |
| /// \return a SYCL range representing the number of work-groups in the |
| /// nd-range. |
| range<Dimensions> get_group_range() const noexcept { |
| return __spirv::initBuiltInNumWorkgroups<Dimensions, range<Dimensions>>(); |
| } |
| |
| /// Equivalent to `return get_group_range()[dimension]`. |
| std::size_t get_group_range(int dimension) const noexcept { |
| return get_group_range()[dimension]; |
| } |
| |
| /// \return a SYCL range representing the maximum number of work-items in any |
| /// work-group in the nd-range. |
| range<Dimensions> get_max_local_range() const noexcept { |
| return get_local_range(); |
| } |
| |
| /// Equivalent to `return get_group_id(dimension)`. |
| std::size_t operator[](int dimension) const noexcept { |
| return get_group_id(dimension); |
| } |
| |
| /// \return the linearized work-group id within the nd-range. |
| std::size_t get_group_linear_id() const noexcept { |
| return detail::linearize_id(get_group_id(), get_group_range()); |
| } |
| |
| /// \return a linearized version of the calling work-item’s local id. |
| std::size_t get_local_linear_id() const noexcept { |
| return detail::linearize_id(get_local_id(), get_local_range()); |
| } |
| |
| /// \return the total number of work-groups in the nd-range. |
| std::size_t get_group_linear_range() const noexcept { |
| auto groupRange = get_group_range(); |
| return multiply_all_dims(groupRange); |
| } |
| |
| /// \return the total number of work-items in this work-group. |
| std::size_t get_local_linear_range() const noexcept { |
| auto localRange = get_local_range(); |
| return multiply_all_dims(localRange); |
| } |
| |
| /// \return true for exactly one work-item in the work-group, if the calling |
| /// work-item is the leader of the work-group, and false for all other |
| /// work-items in the work-group. |
| bool leader() const noexcept { return (get_local_linear_id() == 0); } |
| |
| // TODO: implement parallel_for_work_item, async_work_group_copy and wait_for. |
| |
| protected: |
| group() = default; |
| |
| static std::size_t |
| multiply_all_dims(const range<Dimensions> &Range) noexcept { |
| if constexpr (Dimensions == 1) { |
| return Range[0]; |
| } else if constexpr (Dimensions == 2) { |
| return Range[0] * Range[1]; |
| } else { |
| return Range[0] * Range[1] * Range[2]; |
| } |
| } |
| |
| friend class sycl::nd_item<Dimensions>; |
| }; |
| |
| _LIBSYCL_END_NAMESPACE_SYCL |
| |
| #endif // _LIBSYCL___IMPL_GROUP_HPP |