group-invoke.hh
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @brief Leader-only invocation and leader broadcast for SYCL groups and sub-group partitions.
5///
6/// Installed with the rest of `include/batchlas` (the install rule copies the
7/// tree wholesale); no public header includes it. Not a stable interface.
8/// @ingroup api_internal_helpers
9
11
12#include <sycl/sycl.hpp>
13
14#include <functional>
15#include <type_traits>
16#include <utility>
17
18namespace batchlas {
19
20namespace detail {
21
22template <typename Group>
23using group_type_t = std::remove_cv_t<std::remove_reference_t<Group>>;
24
25template <typename Group>
26inline constexpr bool is_sub_group_v = std::is_same_v<group_type_t<Group>, sycl::sub_group>;
27
28template <typename Group, typename T>
29inline constexpr T broadcast_from_leader_impl(const Group& group, T value) {
30 if constexpr (requires { sg_leader_broadcast(group, value); }) {
31 // SubGroupPartition<P> (sg_partition.hh) provides sg_leader_broadcast() via ADL.
32 return sg_leader_broadcast(group, value);
33 } else {
34 return batchlas::portable::group_broadcast(group, value);
35 }
36}
37
38} // namespace detail
39
40/// @addtogroup api_internal_helpers
41/// @{
42
43/// @brief Calls `fn(args...)` on the group's leader work-item only.
44///
45/// No barrier and no broadcast: other work-items do not see side effects until
46/// the caller synchronises.
47/// @tparam Group any type with `leader()`: a SYCL group, sub-group, or sub-group partition
48template <typename Group, typename Fn, typename... Args>
49inline constexpr void invoke_one(const Group& group, Fn&& fn, Args&&... args) {
50 if (group.leader()) {
51 std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...);
52 }
53}
54
55/// @brief Returns the leader's `value` on every work-item of `group`. Collective.
56///
57/// Uses the group's `sg_leader_broadcast` when one is found by ADL (sub-group
58/// partitions), else `batchlas::portable::group_broadcast` (group-collectives.hh).
59/// @pre `T` is trivially copyable.
60template <typename Group, typename T>
61inline constexpr T broadcast_from_leader(const Group& group, T value) {
62 static_assert(std::is_trivially_copyable_v<T>,
63 "broadcast_from_leader requires T to be trivially copyable");
64 return detail::broadcast_from_leader_impl(group, value);
65}
66
67/// @brief Calls `fn(args...)` on the leader and returns its result on every work-item. Collective.
68/// @return the leader's result; non-leaders contribute a value-initialised placeholder that is discarded
69/// @pre the result type is trivially copyable.
70template <typename Group, typename Fn, typename... Args>
71inline constexpr auto invoke_one_broadcast(const Group& group, Fn&& fn, Args&&... args)
72 -> std::invoke_result_t<Fn, Args...> {
73 using R = std::invoke_result_t<Fn, Args...>;
74 static_assert(std::is_trivially_copyable_v<R>,
75 "invoke_one_broadcast requires return type to be trivially copyable");
76
77 R value{};
78 if (group.leader()) {
79 value = std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...);
80 }
81
82 return detail::broadcast_from_leader_impl(group, value);
83}
84
85/// @}
86
87} // namespace batchlas
batchlas::portable:: group broadcast, shuffles and sums for any trivially copyable or complex T.
constexpr T broadcast_from_leader(const Group &group, T value)
Returns the leader's value on every work-item of group.
constexpr auto invoke_one_broadcast(const Group &group, Fn &&fn, Args &&... args) -> std::invoke_result_t< Fn, Args... >
Calls fn(args...) on the leader and returns its result on every work-item.
T group_broadcast(Group g, T x, Id... id)
sycl::group_broadcast for any trivially copyable T. Collective.
constexpr void invoke_one(const Group &group, Fn &&fn, Args &&... args)
Calls fn(args...) on the group's leader work-item only.
constexpr bool is_sub_group_v
std::remove_cv_t< std::remove_reference_t< Group > > group_type_t
constexpr T broadcast_from_leader_impl(const Group &group, T value)