19#ifdef ALPAKA_ACC_SYCL_ENABLED
21# include <sycl/sycl.hpp>
26 template<
typename TDim>
27 class WarpGenericSycl :
public interface::Implements<alpaka::warp::ConceptWarp, WarpGenericSycl<TDim>>
30 using mask_type = std::uint32_t;
32 WarpGenericSycl(sycl::nd_item<TDim::value> my_item) : m_item_warp{my_item}
36 sycl::nd_item<TDim::value> m_item_warp;
40namespace alpaka::warp::detail
49# if defined(ALPAKA_SYCL_ONEAPI_GPU) && defined(__NO_INLINE__) && !defined(ALPAKA_SYCL_DISABLE_WARP_INLINE_CHECK)
50 constexpr bool syclWarpRequiresInlining =
true;
52 constexpr bool syclWarpRequiresInlining =
false;
56 template<
typename TDim>
57 inline constexpr bool syclWarpSupported = not syclWarpRequiresInlining;
60# define ALPAKA_SYCL_WARP_CHECK_INLINE \
62 alpaka::warp::detail::syclWarpSupported<TDim>, \
63 "The alpaka warp operations give wrong results on Intel GPUs when the SYCL code is compiled without " \
64 "inlining (e.g. -O0, -fno-inline or -fno-inline-functions). Enable optimisations (-O1 or higher) and " \
65 "inlining, or define ALPAKA_SYCL_DISABLE_WARP_INLINE_CHECK if the kernels never return early.")
71# if ALPAKA_COMP_ICPX >= ALPAKA_VERSION_NUMBER(2026, 0, 0)
72 using sycl::ext::oneapi::experimental::this_work_item::get_opportunistic_group;
74 using sycl::ext::oneapi::experimental::this_kernel::get_opportunistic_group;
77 template<
typename TDim>
78 struct GetSize<warp::WarpGenericSycl<TDim>>
80 static auto getSize(warp::WarpGenericSycl<TDim>
const& warp) -> std::int32_t
82 auto const sub_group = warp.m_item_warp.get_sub_group();
84 return static_cast<std::int32_t
>(sub_group.get_max_local_range()[0]);
88 template<
typename TDim>
89 struct GetSizeCompileTime<warp::WarpGenericSycl<TDim>>
98 template<
typename TDim>
99 struct GetSizeUpperLimit<warp::WarpGenericSycl<TDim>>
108 template<
typename TDim>
109 struct Activemask<warp::WarpGenericSycl<TDim>>
114 static auto activemask(warp::WarpGenericSycl<TDim>
const& ) -> warp::WarpGenericSycl<TDim>::mask_type
116 ALPAKA_SYCL_WARP_CHECK_INLINE;
118 sycl::sub_group sg = sycl::ext::oneapi::this_work_item::get_sub_group();
119 auto const mask = sycl::ext::oneapi::group_ballot(sg,
true);
120 std::uint32_t bits = 0;
121 mask.extract_bits(bits);
126 template<
typename TDim>
127 struct All<warp::WarpGenericSycl<TDim>>
129 static auto all(warp::WarpGenericSycl<TDim>
const& , std::int32_t predicate) -> std::int32_t
131 ALPAKA_SYCL_WARP_CHECK_INLINE;
133 auto activegroup = get_opportunistic_group();
134 return static_cast<std::int32_t
>(sycl::all_of_group(activegroup,
static_cast<bool>(predicate)));
138 template<
typename TDim>
139 struct Any<warp::WarpGenericSycl<TDim>>
141 static auto any(warp::WarpGenericSycl<TDim>
const& , std::int32_t predicate) -> std::int32_t
143 ALPAKA_SYCL_WARP_CHECK_INLINE;
145 auto activegroup = get_opportunistic_group();
146 return static_cast<std::int32_t
>(sycl::any_of_group(activegroup,
static_cast<bool>(predicate)));
150 template<
typename TDim>
151 struct Ballot<warp::WarpGenericSycl<TDim>>
156 static auto ballot(warp::WarpGenericSycl<TDim>
const& , std::int32_t predicate)
157 -> warp::WarpGenericSycl<TDim>::mask_type
159 ALPAKA_SYCL_WARP_CHECK_INLINE;
161 auto sub_group = sycl::ext::oneapi::this_work_item::get_sub_group();
162 auto const mask = sycl::ext::oneapi::group_ballot(sub_group,
static_cast<bool>(predicate));
166 std::uint32_t bits = 0;
167 mask.extract_bits(bits);
172 template<
typename TDim>
173 struct Shfl<warp::WarpGenericSycl<TDim>>
177 warp::WarpGenericSycl<TDim>
const& ,
179 std::int32_t srcLane,
182 ALPAKA_SYCL_WARP_CHECK_INLINE;
193 auto actual_group = get_opportunistic_group();
194 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
195 std::uint32_t
const start_index = actual_group.get_local_linear_id() / w * w;
196 return sycl::select_from_group(actual_group, value, start_index +
static_cast<std::uint32_t
>(srcLane) % w);
200 template<
typename TDim>
201 struct ShflUp<warp::WarpGenericSycl<TDim>>
205 warp::WarpGenericSycl<TDim>
const& ,
207 std::uint32_t offset,
210 ALPAKA_SYCL_WARP_CHECK_INLINE;
212 auto actual_group = get_opportunistic_group();
213 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
214 std::uint32_t
const id = actual_group.get_local_linear_id();
215 std::uint32_t
const start_index =
id / w * w;
216 T result = sycl::shift_group_right(actual_group, value, offset);
217 if((
id - start_index) < offset)
225 template<
typename TDim>
226 struct ShflDown<warp::WarpGenericSycl<TDim>>
230 warp::WarpGenericSycl<TDim>
const& ,
232 std::uint32_t offset,
235 ALPAKA_SYCL_WARP_CHECK_INLINE;
237 auto actual_group = get_opportunistic_group();
238 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
239 std::uint32_t
const id = actual_group.get_local_linear_id();
240 std::uint32_t
const end_index = (
id / w + 1) * w;
241 T result = sycl::shift_group_left(actual_group, value, offset);
242 if((
id + offset) >= end_index)
250 template<
typename TDim>
251 struct ShflXor<warp::WarpGenericSycl<TDim>>
255 warp::WarpGenericSycl<TDim>
const& ,
260 ALPAKA_SYCL_WARP_CHECK_INLINE;
262 auto actual_group = get_opportunistic_group();
263 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
264 std::uint32_t
const id = actual_group.get_local_linear_id();
265 std::uint32_t
const start_index =
id / w * w;
266 std::uint32_t
const target_offset = (
id % w) ^
static_cast<std::uint32_t
>(mask);
267 return sycl::select_from_group(actual_group, value, target_offset < w ? start_index + target_offset :
id);
272# undef ALPAKA_SYCL_WARP_CHECK_INLINE
#define ALPAKA_ASSERT_ACC(...)
ALPAKA_ASSERT_ACC is an assert-like macro.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto ballot(TWarp const &warp, std::int32_t predicate) -> typename TWarp::mask_type
Evaluates predicate for all non-exited threads in a warp and returns a 32- or 64-bit unsigned integer...
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto all(TWarp const &warp, std::int32_t predicate) -> std::int32_t
Evaluates predicate for all active threads of the warp and returns non-zero if and only if predicate ...
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto shfl_up(TWarp const &warp, T value, std::uint32_t offset, std::int32_t width=0)
Exchange data between threads within a warp. It copies from a lane with lower ID relative to caller....
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC constexpr auto getSizeUpperLimit() -> std::int32_t
If the warp size is available as a compile-time constant returns its value; otherwise returns an uppe...
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto any(TWarp const &warp, std::int32_t predicate) -> std::int32_t
Evaluates predicate for all active threads of the warp and returns non-zero if and only if predicate ...
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto shfl_down(TWarp const &warp, T value, std::uint32_t offset, std::int32_t width=0)
Exchange data between threads within a warp. It copies from a lane with higher ID relative to caller....
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto getSize(TWarp const &warp) -> std::int32_t
Returns warp size.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto shfl_xor(TWarp const &warp, T value, std::int32_t mask, std::int32_t width=0)
Exchange data between threads within a warp. It copies from a lane based on bitwise XOR of own lane I...
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto activemask(TWarp const &warp) -> typename TWarp::mask_type
Returns a 32- or 64-bit unsigned integer (depending on the accelerator) whose Nth bit is set if and o...
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC constexpr auto getSizeCompileTime() -> std::int32_t
If the warp size is available as a compile-time constant returns its value; otherwise returns 0.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto shfl(TWarp const &warp, T value, std::int32_t srcLane, std::int32_t width=0)
Exchange data between threads within a warp.