RAJA
RAJA provides a collection of platform portability abstractions for C++ HPC applications.
atomic.hpp
Go to the documentation of this file.
1 
11 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
12 // Copyright (c) Lawrence Livermore National Security, LLC and other
13 // RAJA Project Developers. See top-level LICENSE and COPYRIGHT
14 // files for dates and other details. No copyright assignment is required
15 // to contribute to RAJA.
16 //
17 // SPDX-License-Identifier: (BSD-3-Clause)
18 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
19 
20 #ifndef RAJA_policy_openmp_atomic_HPP
21 #define RAJA_policy_openmp_atomic_HPP
22 
23 #include "RAJA/config.hpp"
24 
25 #if defined(RAJA_ENABLE_OPENMP)
26 
28 
29 #include "RAJA/util/macros.hpp"
30 
31 namespace RAJA
32 {
33 
34 // Relies on builtin_atomic when OpenMP can't do the job
35 #if !defined(RAJA_COMPILER_MSVC)
36 
38 template<typename T>
39 RAJA_HOST_DEVICE RAJA_INLINE T atomicLoad(omp_atomic, T* acc)
40 {
41  T ret;
42 #pragma omp atomic capture
43  {
44  ret = *acc; // capture old for return value
45  *acc += (T)0;
46  }
47  return ret;
48 }
49 
51 template<typename T>
52 RAJA_HOST_DEVICE RAJA_INLINE void atomicStore(omp_atomic, T* acc, T value)
53 {
54  T ret;
55 #pragma omp atomic capture
56  {
57  ret = *acc;
58  *acc = value;
59  }
60  RAJA_UNUSED_VAR(ret);
61 }
62 
64 template<typename T>
65 RAJA_HOST_DEVICE RAJA_INLINE T atomicAdd(omp_atomic, T* acc, T value)
66 {
67  T old;
68 #pragma omp atomic capture
69  {
70  old = *acc; // capture old for return value
71  *acc += value;
72  }
73  return old;
74 }
75 
77 template<typename T>
78 RAJA_HOST_DEVICE RAJA_INLINE T atomicSub(omp_atomic, T* acc, T value)
79 {
80  T old;
81 #pragma omp atomic capture
82  {
83  old = *acc; // capture old for return value
84  *acc -= value;
85  }
86  return old;
87 }
88 
90 template<typename T>
91 RAJA_HOST_DEVICE RAJA_INLINE T atomicMin(omp_atomic, T* acc, T value)
92 {
93 #if defined(RAJA_USE_OPENMP_5_1_ATOMICS)
94  T old;
95 #pragma omp atomic capture compare
96  {
97  old = *acc;
98  if (value < *acc)
99  {
100  *acc = value;
101  }
102  }
103  return old;
104 #else
105  // OpenMP doesn't define atomic ternary operators so use builtin atomics
106  return atomicMin(builtin_atomic {}, acc, value);
107 #endif
108 }
109 
111 template<typename T>
112 RAJA_HOST_DEVICE RAJA_INLINE T atomicMax(omp_atomic, T* acc, T value)
113 {
114 #if defined(RAJA_USE_OPENMP_5_1_ATOMICS)
115  T old;
116 #pragma omp atomic capture compare
117  {
118  old = *acc;
119  if (value > *acc)
120  {
121  *acc = value;
122  }
123  }
124  return old;
125 #else
126  // OpenMP doesn't define atomic ternary operators so use builtin atomics
127  return atomicMax(builtin_atomic {}, acc, value);
128 #endif
129 }
130 
132 template<typename T>
133 RAJA_HOST_DEVICE RAJA_INLINE T atomicInc(omp_atomic, T* acc)
134 {
135  T old;
136 #pragma omp atomic capture
137  {
138  old = *acc; // capture old for return value
139  *acc += T(1);
140  }
141  return old;
142 }
143 
145 template<typename T>
146 RAJA_HOST_DEVICE RAJA_INLINE T atomicInc(omp_atomic, T* acc, T value)
147 {
148  // OpenMP doesn't define needed operations, so use builtin atomics
149  return RAJA::atomicInc(builtin_atomic {}, acc, value);
150 }
151 
153 template<typename T>
154 RAJA_HOST_DEVICE RAJA_INLINE T atomicDec(omp_atomic, T* acc)
155 {
156  T old;
157 #pragma omp atomic capture
158  {
159  old = *acc; // capture old for return value
160  *acc -= T(1);
161  }
162  return old;
163 }
164 
166 template<typename T>
167 RAJA_HOST_DEVICE RAJA_INLINE T atomicDec(omp_atomic, T* acc, T value)
168 {
169  // OpenMP doesn't define needed operations, so use builtin atomics
170  return RAJA::atomicDec(builtin_atomic {}, acc, value);
171 }
172 
174 template<typename T>
175 RAJA_HOST_DEVICE RAJA_INLINE T atomicAnd(omp_atomic, T* acc, T value)
176 {
177  T old;
178 #pragma omp atomic capture
179  {
180  old = *acc; // capture old for return value
181  *acc &= value;
182  }
183  return old;
184 }
185 
187 template<typename T>
188 RAJA_HOST_DEVICE RAJA_INLINE T atomicOr(omp_atomic, T* acc, T value)
189 {
190  T old;
191 #pragma omp atomic capture
192  {
193  old = *acc; // capture old for return value
194  *acc |= value;
195  }
196  return old;
197 }
198 
200 template<typename T>
201 RAJA_HOST_DEVICE RAJA_INLINE T atomicXor(omp_atomic, T* acc, T value)
202 {
203  T old;
204 #pragma omp atomic capture
205  {
206  old = *acc; // capture old for return value
207  *acc ^= value;
208  }
209  return old;
210 }
211 
213 template<typename T>
214 RAJA_HOST_DEVICE RAJA_INLINE T atomicExchange(omp_atomic, T* acc, T value)
215 {
216  T old;
217 #pragma omp atomic capture
218  {
219  old = *acc; // capture old for return value
220  *acc = value;
221  }
222  return old;
223 }
224 
226 template<typename T>
227 RAJA_HOST_DEVICE RAJA_INLINE T atomicCAS(omp_atomic, T* acc, T compare, T value)
228 {
229  // OpenMP doesn't define atomic ternary operators so use builtin atomics
230  return RAJA::atomicCAS(builtin_atomic {}, acc, compare, value);
231 }
232 
233 #endif // not defined RAJA_COMPILER_MSVC
234 
235 
236 } // namespace RAJA
237 
238 #endif // RAJA_ENABLE_OPENMP
239 #endif // guard
Header file for common RAJA internal macro definitions.
RAJA_HOST_DEVICE RAJA_INLINE void RAJA_UNUSED_VAR(T &&...) noexcept
Definition: macros.hpp:120
#define RAJA_HOST_DEVICE
Definition: macros.hpp:65
#define RAJA_SUPPRESS_HD_WARN
Definition: macros.hpp:68
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_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_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_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_INLINE RAJA_HOST_DEVICE void atomicStore(T *acc, T value)
Atomic store.
Definition: atomic.hpp:104
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_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_INLINE RAJA_HOST_DEVICE T atomicSub(T *acc, T value)
Atomic subtract.
Definition: atomic.hpp:130
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE T atomicExchange(T *acc, T value)
Atomic value exchange.
Definition: atomic.hpp:271
Header file containing RAJA OpenMP policy definitions.