21#ifdef ALPAKA_ACC_SYCL_ENABLED
23# include <sycl/sycl.hpp>
28 template<
typename TDim>
29 class WarpGenericSycl :
public interface::Implements<alpaka::warp::ConceptWarp, WarpGenericSycl<TDim>>
32 using mask_type = std::uint32_t;
34 WarpGenericSycl(sycl::nd_item<TDim::value> my_item) : m_item_warp{my_item}
38 sycl::nd_item<TDim::value> m_item_warp;
57# define ALPAKA_SYCL_WARP_UNSUPPORTED_FPGA "The alpaka warp operations are not supported on Intel/Altera FPGAs."
58# define ALPAKA_SYCL_WARP_UNSUPPORTED_AMD \
59 "The alpaka warp operations are not supported by the SYCL backend on AMD GPUs."
60# if ALPAKA_COMP_ICPX < ALPAKA_VERSION_NUMBER(2025, 2, 0)
61# define ALPAKA_SYCL_WARP_UNSUPPORTED_INTEL \
62 "The alpaka warp operations require oneAPI 2025.2 or newer on Intel CPUs and GPUs."
63# elif ALPAKA_COMP_ICPX < ALPAKA_VERSION_NUMBER(2026, 2, 0) && defined(__NO_INLINE__) \
64 && !defined(ALPAKA_SYCL_DISABLE_WARP_INLINE_CHECK)
65# define ALPAKA_SYCL_WARP_UNSUPPORTED_INTEL \
66 "The alpaka warp operations give wrong results on Intel CPUs and GPUs with oneAPI 2026.1 and older, " \
67 "when the SYCL code is compiled without inlining (e.g. -O0, -fno-inline or -fno-inline-functions). " \
68 "Enable optimisations (-O1 or higher) and inlining, or define ALPAKA_SYCL_DISABLE_WARP_INLINE_CHECK if " \
69 "the kernels never return early."
71# if ALPAKA_COMP_ICPX < ALPAKA_VERSION_NUMBER(2025, 0, 0)
72# define ALPAKA_SYCL_WARP_UNSUPPORTED_NVIDIA \
73 "The alpaka warp operations require oneAPI 2025.0 or newer on NVIDIA GPUs."
77# ifdef __SYCL_DEVICE_ONLY__
78# if defined(__NVPTX__)
79# ifdef ALPAKA_SYCL_WARP_UNSUPPORTED_NVIDIA
80# define ALPAKA_SYCL_WARP_UNSUPPORTED ALPAKA_SYCL_WARP_UNSUPPORTED_NVIDIA
82# elif defined(__AMDGCN__)
83# define ALPAKA_SYCL_WARP_UNSUPPORTED ALPAKA_SYCL_WARP_UNSUPPORTED_AMD
84# elif defined(ALPAKA_SYCL_ONEAPI_FPGA) && !defined(ALPAKA_SYCL_ONEAPI_GPU) \
85 && !(defined(__SYCL_TARGET_INTEL_X86_64__) && __SYCL_TARGET_INTEL_X86_64__)
88# define ALPAKA_SYCL_WARP_UNSUPPORTED ALPAKA_SYCL_WARP_UNSUPPORTED_FPGA
89# elif defined(ALPAKA_SYCL_WARP_UNSUPPORTED_INTEL)
91# define ALPAKA_SYCL_WARP_UNSUPPORTED ALPAKA_SYCL_WARP_UNSUPPORTED_INTEL
95namespace alpaka::warp::detail
99 template<
typename TTag>
100 constexpr auto syclWarpUnsupportedReason() ->
char const*
102 if constexpr(std::is_same_v<TTag, TagFpgaSyclIntel>)
104 return ALPAKA_SYCL_WARP_UNSUPPORTED_FPGA;
106 else if constexpr(std::is_same_v<TTag, TagGpuSyclAmd>)
108 return ALPAKA_SYCL_WARP_UNSUPPORTED_AMD;
110 else if constexpr(std::is_same_v<TTag, TagGpuSyclNvidia>)
112# ifdef ALPAKA_SYCL_WARP_UNSUPPORTED_NVIDIA
113 return ALPAKA_SYCL_WARP_UNSUPPORTED_NVIDIA;
121# ifdef ALPAKA_SYCL_WARP_UNSUPPORTED_INTEL
122 return ALPAKA_SYCL_WARP_UNSUPPORTED_INTEL;
130 template<
typename TDim>
131 inline constexpr bool syclWarpDependentFalse =
false;
134# ifdef ALPAKA_SYCL_WARP_UNSUPPORTED
135# define ALPAKA_SYCL_WARP_CHECK \
136 static_assert(alpaka::warp::detail::syclWarpDependentFalse<TDim>, ALPAKA_SYCL_WARP_UNSUPPORTED)
138# define ALPAKA_SYCL_WARP_CHECK static_assert(true)
145# if ALPAKA_COMP_ICPX >= ALPAKA_VERSION_NUMBER(2026, 0, 0)
146 using sycl::ext::oneapi::experimental::this_work_item::get_opportunistic_group;
148 using sycl::ext::oneapi::experimental::this_kernel::get_opportunistic_group;
151 template<
typename TDim>
152 struct GetSize<warp::WarpGenericSycl<TDim>>
154 static auto getSize(warp::WarpGenericSycl<TDim>
const& warp) -> std::int32_t
156 auto const sub_group = warp.m_item_warp.get_sub_group();
158 return static_cast<std::int32_t
>(sub_group.get_max_local_range()[0]);
162 template<
typename TDim>
163 struct GetSizeCompileTime<warp::WarpGenericSycl<TDim>>
172 template<
typename TDim>
173 struct GetSizeUpperLimit<warp::WarpGenericSycl<TDim>>
182 template<
typename TDim>
183 struct Activemask<warp::WarpGenericSycl<TDim>>
188 static auto activemask(warp::WarpGenericSycl<TDim>
const& ) -> warp::WarpGenericSycl<TDim>::mask_type
190 ALPAKA_SYCL_WARP_CHECK;
192 sycl::sub_group sg = sycl::ext::oneapi::this_work_item::get_sub_group();
193 auto const mask = sycl::ext::oneapi::group_ballot(sg,
true);
194 std::uint32_t bits = 0;
195 mask.extract_bits(bits);
200 template<
typename TDim>
201 struct All<warp::WarpGenericSycl<TDim>>
203 static auto all(warp::WarpGenericSycl<TDim>
const& , std::int32_t predicate) -> std::int32_t
205 ALPAKA_SYCL_WARP_CHECK;
207 auto activegroup = get_opportunistic_group();
208 return static_cast<std::int32_t
>(sycl::all_of_group(activegroup,
static_cast<bool>(predicate)));
212 template<
typename TDim>
213 struct Any<warp::WarpGenericSycl<TDim>>
215 static auto any(warp::WarpGenericSycl<TDim>
const& , std::int32_t predicate) -> std::int32_t
217 ALPAKA_SYCL_WARP_CHECK;
219 auto activegroup = get_opportunistic_group();
220 return static_cast<std::int32_t
>(sycl::any_of_group(activegroup,
static_cast<bool>(predicate)));
224 template<
typename TDim>
225 struct Ballot<warp::WarpGenericSycl<TDim>>
230 static auto ballot(warp::WarpGenericSycl<TDim>
const& , std::int32_t predicate)
231 -> warp::WarpGenericSycl<TDim>::mask_type
233 ALPAKA_SYCL_WARP_CHECK;
235 auto sub_group = sycl::ext::oneapi::this_work_item::get_sub_group();
236 auto const mask = sycl::ext::oneapi::group_ballot(sub_group,
static_cast<bool>(predicate));
240 std::uint32_t bits = 0;
241 mask.extract_bits(bits);
246 template<
typename TDim>
247 struct Shfl<warp::WarpGenericSycl<TDim>>
251 warp::WarpGenericSycl<TDim>
const& ,
253 std::int32_t srcLane,
256 ALPAKA_SYCL_WARP_CHECK;
267 auto actual_group = get_opportunistic_group();
268 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
269 std::uint32_t
const start_index = actual_group.get_local_linear_id() / w * w;
270 return sycl::select_from_group(actual_group, value, start_index +
static_cast<std::uint32_t
>(srcLane) % w);
274 template<
typename TDim>
275 struct ShflUp<warp::WarpGenericSycl<TDim>>
279 warp::WarpGenericSycl<TDim>
const& ,
281 std::uint32_t offset,
284 ALPAKA_SYCL_WARP_CHECK;
286 auto actual_group = get_opportunistic_group();
287 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
288 std::uint32_t
const id = actual_group.get_local_linear_id();
289 std::uint32_t
const start_index =
id / w * w;
290 T result = sycl::shift_group_right(actual_group, value, offset);
291 if((
id - start_index) < offset)
299 template<
typename TDim>
300 struct ShflDown<warp::WarpGenericSycl<TDim>>
304 warp::WarpGenericSycl<TDim>
const& ,
306 std::uint32_t offset,
309 ALPAKA_SYCL_WARP_CHECK;
311 auto actual_group = get_opportunistic_group();
312 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
313 std::uint32_t
const id = actual_group.get_local_linear_id();
314 std::uint32_t
const end_index = (
id / w + 1) * w;
315 T result = sycl::shift_group_left(actual_group, value, offset);
316 if((
id + offset) >= end_index)
324 template<
typename TDim>
325 struct ShflXor<warp::WarpGenericSycl<TDim>>
329 warp::WarpGenericSycl<TDim>
const& ,
334 ALPAKA_SYCL_WARP_CHECK;
336 auto actual_group = get_opportunistic_group();
337 std::uint32_t
const w =
static_cast<std::uint32_t
>(width);
338 std::uint32_t
const id = actual_group.get_local_linear_id();
339 std::uint32_t
const start_index =
id / w * w;
340 std::uint32_t
const target_offset = (
id % w) ^
static_cast<std::uint32_t
>(mask);
341 return sycl::select_from_group(actual_group, value, target_offset < w ? start_index + target_offset :
id);
346# undef ALPAKA_SYCL_WARP_CHECK
347# undef ALPAKA_SYCL_WARP_UNSUPPORTED
348# undef ALPAKA_SYCL_WARP_UNSUPPORTED_FPGA
349# undef ALPAKA_SYCL_WARP_UNSUPPORTED_AMD
350# undef ALPAKA_SYCL_WARP_UNSUPPORTED_INTEL
351# undef ALPAKA_SYCL_WARP_UNSUPPORTED_NVIDIA
#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.