13 #include <type_traits>
15 #ifdef ALPAKA_ACC_SYCL_ENABLED
17 # include <sycl/sycl.hpp>
25 class AtomicGenericSycl
31 template<
typename THierarchy>
32 struct SyclMemoryScope
37 struct SyclMemoryScope<hierarchy::Grids>
39 static constexpr
auto value = sycl::memory_scope::device;
43 struct SyclMemoryScope<hierarchy::Blocks>
45 static constexpr
auto value = sycl::memory_scope::device;
49 struct SyclMemoryScope<hierarchy::Threads>
51 static constexpr
auto value = sycl::memory_scope::work_group;
54 template<
typename T,
typename THierarchy>
55 using sycl_atomic_ref = sycl::atomic_ref<T, sycl::memory_order::relaxed, SyclMemoryScope<THierarchy>::value>;
57 template<
typename THierarchy,
typename T,
typename TOp>
58 inline auto callAtomicOp(T*
const addr, TOp&& op)
60 auto ref = sycl_atomic_ref<T, THierarchy>{*addr};
64 template<
typename TRef,
typename T,
typename TEval>
65 inline auto casWithCondition(T*
const addr, TEval&& eval)
67 auto ref = TRef{*addr};
68 auto old_val = ref.load();
71 while(!ref.compare_exchange_weak(old_val, eval(old_val)))
84 template<
typename T,
typename THierarchy>
85 struct AtomicOp<AtomicAdd, AtomicGenericSycl, T, THierarchy>
87 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
"SYCL atomics do not support this type");
89 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
91 return alpaka::detail::callAtomicOp<THierarchy>(
93 [&value](
auto& ref) {
return ref.fetch_add(value); });
99 template<
typename T,
typename THierarchy>
100 struct AtomicOp<AtomicSub, AtomicGenericSycl, T, THierarchy>
102 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
"SYCL atomics do not support this type");
104 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
106 return alpaka::detail::callAtomicOp<THierarchy>(
108 [&value](
auto& ref) {
return ref.fetch_sub(value); });
114 template<
typename T,
typename THierarchy>
115 struct AtomicOp<AtomicMin, AtomicGenericSycl, T, THierarchy>
117 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
"SYCL atomics do not support this type");
119 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
121 return alpaka::detail::callAtomicOp<THierarchy>(
123 [&value](
auto& ref) {
return ref.fetch_min(value); });
129 template<
typename T,
typename THierarchy>
130 struct AtomicOp<AtomicMax, AtomicGenericSycl, T, THierarchy>
132 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
"SYCL atomics do not support this type");
134 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
136 return alpaka::detail::callAtomicOp<THierarchy>(
138 [&value](
auto& ref) {
return ref.fetch_max(value); });
144 template<
typename T,
typename THierarchy>
145 struct AtomicOp<AtomicExch, AtomicGenericSycl, T, THierarchy>
148 (std::is_integral_v<T> || std::is_floating_point_v<T>) and(
sizeof(T) == 4 ||
sizeof(T) == 8),
149 "SYCL atomics do not support this type");
151 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
153 return alpaka::detail::callAtomicOp<THierarchy>(addr, [&value](
auto& ref) {
return ref.exchange(value); });
159 template<
typename T,
typename THierarchy>
160 struct AtomicOp<AtomicInc, AtomicGenericSycl, T, THierarchy>
163 std::is_unsigned_v<T> && (
sizeof(T) == 4 ||
sizeof(T) == 8),
164 "SYCL atomics support only 32- and 64-bits unsigned integral types");
166 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
168 auto inc = [&value](
auto old_val)
169 {
return (old_val >= value) ?
static_cast<T
>(0) : (old_val +
static_cast<T
>(1)); };
170 return alpaka::detail::casWithCondition<alpaka::detail::sycl_atomic_ref<T, THierarchy>>(addr, inc);
176 template<
typename T,
typename THierarchy>
177 struct AtomicOp<AtomicDec, AtomicGenericSycl, T, THierarchy>
180 std::is_unsigned_v<T> && (
sizeof(T) == 4 ||
sizeof(T) == 8),
181 "SYCL atomics support only 32- and 64-bits unsigned integral types");
183 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
185 auto dec = [&value](
auto& old_val)
186 {
return ((old_val == 0) || (old_val > value)) ? value : (old_val -
static_cast<T
>(1)); };
187 return alpaka::detail::casWithCondition<alpaka::detail::sycl_atomic_ref<T, THierarchy>>(addr, dec);
193 template<
typename T,
typename THierarchy>
194 struct AtomicOp<AtomicAnd, AtomicGenericSycl, T, THierarchy>
196 static_assert(std::is_integral_v<T>,
"Bitwise operations only supported for integral types.");
198 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
200 return alpaka::detail::callAtomicOp<THierarchy>(
202 [&value](
auto& ref) {
return ref.fetch_and(value); });
208 template<
typename T,
typename THierarchy>
209 struct AtomicOp<AtomicOr, AtomicGenericSycl, T, THierarchy>
211 static_assert(std::is_integral_v<T>,
"Bitwise operations only supported for integral types.");
213 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
215 return alpaka::detail::callAtomicOp<THierarchy>(addr, [&value](
auto& ref) {
return ref.fetch_or(value); });
221 template<
typename T,
typename THierarchy>
222 struct AtomicOp<AtomicXor, AtomicGenericSycl, T, THierarchy>
224 static_assert(std::is_integral_v<T>,
"Bitwise operations only supported for integral types.");
226 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& value) -> T
228 return alpaka::detail::callAtomicOp<THierarchy>(
230 [&value](
auto& ref) {
return ref.fetch_xor(value); });
236 template<
typename T,
typename THierarchy>
237 struct AtomicOp<AtomicCas, AtomicGenericSycl, T, THierarchy>
239 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
"SYCL atomics do not support this type");
241 static auto atomicOp(AtomicGenericSycl
const&, T*
const addr, T
const& expected, T
const& desired) -> T
243 auto cas = [&expected, &desired](
auto& ref)
245 auto expected_ = expected;
251 ref.compare_exchange_strong(expected_, desired);
258 return alpaka::detail::callAtomicOp<THierarchy>(addr, cas);
The alpaka accelerator library.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto atomicOp(TAtomic const &atomic, T *const addr, T const &value, THierarchy const &=THierarchy()) -> T
Executes the given operation atomically.