20 #ifndef RAJA_policy_hip_atomic_HPP
21 #define RAJA_policy_hip_atomic_HPP
23 #include "RAJA/config.hpp"
25 #if defined(RAJA_ENABLE_HIP)
29 #include <type_traits>
30 #include "hip/hip_runtime.h"
32 #include "camp/list.hpp"
37 #if defined(RAJA_OPENMP_ACTIVE)
55 using hip_atomicCommon_builtin_types =
56 ::camp::list<int, unsigned int, unsigned long long>;
65 struct hip_useBuiltinCommon
67 static constexpr
bool value = std::is_same<T, int>::value ||
68 std::is_same<T, unsigned int>::value ||
69 std::is_same<T, unsigned long long>::value;
80 struct hip_useReinterpretCommon
82 static constexpr
bool value = !hip_useBuiltinCommon<T>::value &&
83 (
sizeof(T) ==
sizeof(
unsigned int) ||
84 sizeof(T) ==
sizeof(
unsigned long long));
86 using type = std::conditional_t<
sizeof(T) ==
sizeof(
unsigned int),
95 using hip_useReinterpretCommon_t =
typename hip_useReinterpretCommon<T>::type;
105 std::enable_if_t<hip_useBuiltinCommon<T>::value,
bool> =
true>
106 RAJA_INLINE __device__ T hip_atomicOr(T* acc, T value)
116 struct hip_useBuiltinExchange
118 static constexpr
bool value = std::is_same<T, int>::value ||
119 std::is_same<T, unsigned int>::value ||
120 std::is_same<T, unsigned long long>::value ||
121 std::is_same<T, float>::value;
129 struct hip_useReinterpretExchange
131 static constexpr
bool value = !hip_useBuiltinExchange<T>::value &&
132 (
sizeof(T) ==
sizeof(
unsigned int) ||
133 sizeof(T) ==
sizeof(
unsigned long long));
135 using type = std::conditional_t<
sizeof(T) ==
sizeof(
unsigned int),
144 using hip_useReinterpretExchange_t =
145 typename hip_useReinterpretExchange<T>::type;
152 std::enable_if_t<hip_useBuiltinExchange<T>::value,
bool> =
true>
153 RAJA_INLINE __device__ T hip_atomicExchange(T* acc, T value)
155 return ::atomicExch(acc, value);
163 std::enable_if_t<hip_useReinterpretExchange<T>::value,
bool> =
true>
164 RAJA_INLINE __device__ T hip_atomicExchange(T* acc, T value)
166 using R = hip_useReinterpretExchange_t<T>;
168 return RAJA::util::reinterp_A_as_B<R, T>(hip_atomicExchange(
169 reinterpret_cast<R*
>(acc), RAJA::util::reinterp_A_as_B<T, R>(value)));
173 #if defined(__has_builtin) && \
174 (__has_builtin(__hip_atomic_load) || __has_builtin(__hip_atomic_store))
181 struct hip_useBuiltinLoad
183 static constexpr
bool value =
184 (std::is_integral<T>::value || std::is_enum<T>::value) &&
185 (
sizeof(T) == 1 ||
sizeof(T) == 2 ||
sizeof(T) == 4 ||
sizeof(T) == 8);
189 using hip_useBuiltinStore = hip_useBuiltinLoad<T>;
196 struct hip_useReinterpretLoad
198 static constexpr
bool value = !std::is_integral<T>::value &&
199 !std::is_enum<T>::value &&
201 #
if !defined(UINT8_MAX)
202 &&
sizeof(
unsigned char) == 1
206 #
if !defined(UINT16_MAX)
207 &&
sizeof(
unsigned short) == 2
211 #
if !defined(UINT32_MAX)
212 &&
sizeof(
unsigned int) == 4
216 #
if !defined(UINT64_MAX)
217 &&
sizeof(
unsigned long long) == 8
222 std::conditional_t<
sizeof(T) == 1,
223 #
if defined(UINT8_MAX)
228 std::conditional_t<
sizeof(T) == 2,
229 #
if defined(UINT16_MAX)
234 std::conditional_t<
sizeof(T) == 4,
235 #
if defined(UINT32_MAX)
240 #if defined(UINT64_MAX)
243 unsigned long long>>>;
248 using hip_useReinterpretStore = hip_useReinterpretLoad<T>;
253 using hip_useBuiltinLoad = hip_useBuiltinCommon<T>;
256 using hip_useBuiltinStore = hip_useBuiltinExchange<T>;
262 using hip_useReinterpretLoad = hip_useReinterpretCommon<T>;
265 using hip_useReinterpretStore = hip_useReinterpretExchange<T>;
273 using hip_useReinterpretLoad_t =
typename hip_useReinterpretLoad<T>::type;
276 using hip_useReinterpretStore_t =
typename hip_useReinterpretStore<T>::type;
282 std::enable_if_t<hip_useBuiltinLoad<T>::value,
bool> =
true>
283 RAJA_INLINE __device__ T hip_atomicLoad(T* acc)
285 #if defined(__has_builtin) && __has_builtin(__hip_atomic_load)
286 return __hip_atomic_load(acc, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
288 return hip_atomicOr(acc,
static_cast<T
>(0));
293 std::enable_if_t<hip_useReinterpretLoad<T>::value,
bool> =
true>
294 RAJA_INLINE __device__ T hip_atomicLoad(T* acc)
296 using R = hip_useReinterpretLoad_t<T>;
298 return RAJA::util::reinterp_A_as_B<R, T>(
299 hip_atomicLoad(
reinterpret_cast<R*
>(acc)));
306 std::enable_if_t<hip_useBuiltinStore<T>::value,
bool> =
true>
307 RAJA_INLINE __device__
void hip_atomicStore(T* acc, T value)
309 #if defined(__has_builtin) && __has_builtin(__hip_atomic_store)
310 __hip_atomic_store(acc, value, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
312 hip_atomicExchange(acc, value);
317 std::enable_if_t<hip_useReinterpretStore<T>::value,
bool> =
true>
318 RAJA_INLINE __device__
void hip_atomicStore(T* acc, T value)
320 using R = hip_useReinterpretStore_t<T>;
322 hip_atomicStore(
reinterpret_cast<R*
>(acc),
323 RAJA::util::reinterp_A_as_B<T, R>(value));
332 std::enable_if_t<hip_useBuiltinCommon<T>::value,
bool> =
true>
333 RAJA_INLINE __device__ T hip_atomicCAS(T* acc, T compare, T value)
344 std::enable_if_t<hip_useReinterpretCommon<T>::value,
bool> =
true>
345 RAJA_INLINE __device__ T hip_atomicCAS(T* acc, T compare, T value)
347 using R = hip_useReinterpretCommon_t<T>;
349 return RAJA::util::reinterp_A_as_B<R, T>(hip_atomicCAS(
350 reinterpret_cast<R*
>(acc), RAJA::util::reinterp_A_as_B<T, R>(compare),
351 RAJA::util::reinterp_A_as_B<T, R>(value)));
360 std::enable_if_t<hip_useBuiltinCommon<T>::value,
bool> =
true>
361 RAJA_INLINE __device__
bool hip_atomicCAS_equal(
const T& a,
const T& b)
367 std::enable_if_t<hip_useReinterpretCommon<T>::value,
bool> =
true>
368 RAJA_INLINE __device__
bool hip_atomicCAS_equal(
const T& a,
const T& b)
370 using R = hip_useReinterpretCommon_t<T>;
372 return hip_atomicCAS_equal(RAJA::util::reinterp_A_as_B<T, R>(a),
373 RAJA::util::reinterp_A_as_B<T, R>(b));
382 template<
typename T,
typename Oper>
383 RAJA_INLINE __device__ T hip_atomicCAS_loop(T* acc, Oper&& oper)
385 T old = hip_atomicLoad(acc);
391 old = hip_atomicCAS(acc, expected, oper(expected));
392 }
while (!hip_atomicCAS_equal(old, expected));
403 template<
typename T,
typename Oper,
typename ShortCircuit>
404 RAJA_INLINE __device__ T hip_atomicCAS_loop(T* acc,
408 T old = hip_atomicLoad(acc);
420 old = hip_atomicCAS(acc, expected, oper(expected));
421 }
while (!hip_atomicCAS_equal(old, expected) && !sc(old));
433 using hip_atomicAdd_builtin_types = ::camp::list<int,
437 #ifdef RAJA_ENABLE_HIP_DOUBLE_ATOMICADD
446 RAJA_INLINE __device__ T hip_atomicAdd(T* acc, T value)
448 return hip_atomicCAS_loop(acc, [value](T old) {
456 RAJA_INLINE __device__ T hip_atomicAdd(T* acc, T value)
468 using hip_atomicSub_builtin_types = ::camp::list<int,
472 #ifdef RAJA_ENABLE_HIP_DOUBLE_ATOMICADD
484 using hip_atomicSub_via_Sub_builtin_types = ::camp::list<int, unsigned int>;
492 using hip_atomicSub_via_Add_builtin_types = ::camp::list<
unsigned long long,
494 #ifdef RAJA_ENABLE_HIP_DOUBLE_ATOMICADD
506 RAJA_INLINE __device__ T hip_atomicSub(T* acc, T value)
508 return hip_atomicCAS_loop(acc, [value](T old) {
520 RAJA_INLINE __device__ T hip_atomicSub(T* acc, T value)
532 RAJA_INLINE __device__ T hip_atomicSub(T* acc, T value)
540 using hip_atomicMin_builtin_types = hip_atomicCommon_builtin_types;
545 RAJA_INLINE __device__ T hip_atomicMin(T* acc, T value)
547 return hip_atomicCAS_loop(
550 return value < old ? value : old;
553 return current <= value;
560 RAJA_INLINE __device__ T hip_atomicMin(T* acc, T value)
568 using hip_atomicMax_builtin_types = hip_atomicCommon_builtin_types;
573 RAJA_INLINE __device__ T hip_atomicMax(T* acc, T value)
575 return hip_atomicCAS_loop(
578 return old < value ? value : old;
581 return value <= current;
588 RAJA_INLINE __device__ T hip_atomicMax(T* acc, T value)
597 RAJA_INLINE __device__ T hip_atomicInc(T* acc, T value)
599 return hip_atomicCAS_loop(acc, [value](T old) {
600 return value <= old ? static_cast<T>(0) : old + static_cast<T>(1);
608 RAJA_INLINE __device__ T hip_atomicInc(T* acc)
610 return hip_atomicAdd(acc,
static_cast<T
>(1));
617 RAJA_INLINE __device__ T hip_atomicDec(T* acc, T value)
619 return hip_atomicCAS_loop(acc, [value](T old) {
620 return old ==
static_cast<T
>(0) || value < old ? value
621 : old -
static_cast<T
>(1);
629 RAJA_INLINE __device__ T hip_atomicDec(T* acc)
631 return hip_atomicSub(acc,
static_cast<T
>(1));
637 using hip_atomicAnd_builtin_types = hip_atomicCommon_builtin_types;
642 RAJA_INLINE __device__ T hip_atomicAnd(T* acc, T value)
644 return hip_atomicCAS_loop(acc, [value](T old) {
652 RAJA_INLINE __device__ T hip_atomicAnd(T* acc, T value)
660 using hip_atomicOr_builtin_types = hip_atomicCommon_builtin_types;
665 RAJA_INLINE __device__ T hip_atomicOr(T* acc, T value)
667 return hip_atomicCAS_loop(acc, [value](T old) {
681 using hip_atomicXor_builtin_types = hip_atomicCommon_builtin_types;
686 RAJA_INLINE __device__ T hip_atomicXor(T* acc, T value)
688 return hip_atomicCAS_loop(acc, [value](T old) {
696 RAJA_INLINE __device__ T hip_atomicXor(T* acc, T value)
714 template<
typename T,
typename host_policy>
718 #if defined(__HIP_DEVICE_COMPILE__)
719 return detail::hip_atomicLoad(acc);
726 template<
typename T,
typename host_policy>
731 #if defined(__HIP_DEVICE_COMPILE__)
732 detail::hip_atomicStore(acc, value);
739 template<
typename T,
typename host_policy>
744 #if defined(__HIP_DEVICE_COMPILE__)
745 return detail::hip_atomicAdd(acc, value);
752 template<
typename T,
typename host_policy>
757 #if defined(__HIP_DEVICE_COMPILE__)
758 return detail::hip_atomicSub(acc, value);
765 template<
typename T,
typename host_policy>
770 #if defined(__HIP_DEVICE_COMPILE__)
771 return detail::hip_atomicMin(acc, value);
778 template<
typename T,
typename host_policy>
783 #if defined(__HIP_DEVICE_COMPILE__)
784 return detail::hip_atomicMax(acc, value);
791 template<
typename T,
typename host_policy>
796 #if defined(__HIP_DEVICE_COMPILE__)
797 return detail::hip_atomicInc(acc, value);
804 template<
typename T,
typename host_policy>
808 #if defined(__HIP_DEVICE_COMPILE__)
809 return detail::hip_atomicInc(acc);
816 template<
typename T,
typename host_policy>
821 #if defined(__HIP_DEVICE_COMPILE__)
822 return detail::hip_atomicDec(acc, value);
829 template<
typename T,
typename host_policy>
833 #if defined(__HIP_DEVICE_COMPILE__)
834 return detail::hip_atomicDec(acc);
841 template<
typename T,
typename host_policy>
846 #if defined(__HIP_DEVICE_COMPILE__)
847 return detail::hip_atomicAnd(acc, value);
854 template<
typename T,
typename host_policy>
859 #if defined(__HIP_DEVICE_COMPILE__)
860 return detail::hip_atomicOr(acc, value);
867 template<
typename T,
typename host_policy>
872 #if defined(__HIP_DEVICE_COMPILE__)
873 return detail::hip_atomicXor(acc, value);
880 template<
typename T,
typename host_policy>
885 #if defined(__HIP_DEVICE_COMPILE__)
886 return detail::hip_atomicExchange(acc, value);
893 template<
typename T,
typename host_policy>
895 atomicCAS(hip_atomic_explicit<host_policy>, T* acc, T compare, T value)
897 #if defined(__HIP_DEVICE_COMPILE__)
898 return detail::hip_atomicCAS(acc, compare, value);
Header file for enable_if helpers.
Header file for RAJA operator definitions.
Header file for reinterpreting type conversions.
RAJA header file defining automatic and builtin atomic operations.
Header file for common RAJA internal macro definitions.
#define RAJA_HOST_DEVICE
Definition: macros.hpp:65
#define RAJA_SUPPRESS_HD_WARN
Definition: macros.hpp:68
std::enable_if_t< is_any_of< T, TypeList >::value, T > enable_if_is_any_of
Definition: EnableIf.hpp:49
std::enable_if_t<::RAJA::concepts::negate< is_any_of< T, TypeList > >::value, T > enable_if_is_none_of
Definition: EnableIf.hpp:54
Definition: AlignedRangeIndexSetBuilders.cpp:35
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicAnd(T *acc, T value)
Atomic bitwise AND equivalent to (*acc) = (*acc) & value This only works with integral data types.
Definition: atomic.hpp:224
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicCAS(seq_atomic, T *acc, T compare, T value)
Definition: atomic.hpp:154
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicOr(T *acc, T value)
Atomic bitwise OR equivalent to (*acc) = (*acc) | value This only works with integral data types.
Definition: atomic.hpp:240
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicMax(seq_atomic, T *acc, T value)
Definition: atomic.hpp:73
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicLoad(T *acc)
Atomic load.
Definition: atomic.hpp:92
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicDec(T *acc)
Atomic decrement.
Definition: atomic.hpp:195
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicAdd(T *acc, T value)
Atomic add.
Definition: atomic.hpp:117
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicSub(seq_atomic, T *acc, T value)
Definition: atomic.hpp:55
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicXor(T *acc, T value)
Atomic bitwise XOR equivalent to (*acc) = (*acc) ^ value This only works with integral data types.
Definition: atomic.hpp:256
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicXor(seq_atomic, T *acc, T value)
Definition: atomic.hpp:136
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE void atomicStore(T *acc, T value)
Atomic store.
Definition: atomic.hpp:104
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicAnd(seq_atomic, T *acc, T value)
Definition: atomic.hpp:118
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicMax(T *acc, T value)
Atomic maximum equivalent to (*acc) = std::max(*acc, value)
Definition: atomic.hpp:156
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicCAS(T *acc, T compare, T value)
Atomic compare and swap.
Definition: atomic.hpp:286
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicInc(T *acc)
Atomic increment.
Definition: atomic.hpp:168
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicAdd(seq_atomic, T *acc, T value)
Definition: atomic.hpp:46
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicMin(T *acc, T value)
Atomic minimum equivalent to (*acc) = std::min(*acc, value)
Definition: atomic.hpp:143
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicMin(seq_atomic, T *acc, T value)
Definition: atomic.hpp:64
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicSub(T *acc, T value)
Atomic subtract.
Definition: atomic.hpp:130
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE T atomicOr(seq_atomic, T *acc, T value)
Definition: atomic.hpp:127
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicExchange(T *acc, T value)
Atomic value exchange.
Definition: atomic.hpp:271
RAJA header file defining OpenMP atomic operations.
RAJA header file defining sequential atomic operations.