alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
AtomicOmpBuiltIn.hpp
Go to the documentation of this file.
1/* Copyright 2022 René Widera, Bernhard Manfred Gruber
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
10
11#ifdef _OPENMP
12
13namespace alpaka
14{
15 //! The OpenMP accelerators atomic ops.
16 //
17 // Atomics can be used in the blocks and threads hierarchy levels.
18 // Atomics are not guaranteed to be safe between devices or grids.
20 {
21 };
22
23 namespace trait
24 {
25// check for OpenMP 3.1+
26// "omp atomic capture" is not supported before OpenMP 3.1
27# if _OPENMP >= 201107
28
29 //! The OpenMP accelerators atomic operation: ADD
30 template<typename T, typename THierarchy>
31 struct AtomicOp<AtomicAdd, AtomicOmpBuiltIn, T, THierarchy>
32 {
33 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
34 {
35 T old;
36 auto& ref(*addr);
37// atomically update ref, but capture the original value in old
38# if BOOST_COMP_GNUC
39# pragma GCC diagnostic push
40# pragma GCC diagnostic ignored "-Wconversion"
41# endif
42# pragma omp atomic capture
43 {
44 old = ref;
45 ref += value;
46 }
47# if BOOST_COMP_GNUC
48# pragma GCC diagnostic pop
49# endif
50 return old;
51 }
52 };
53
54 //! The OpenMP accelerators atomic operation: SUB
55 template<typename T, typename THierarchy>
56 struct AtomicOp<AtomicSub, AtomicOmpBuiltIn, T, THierarchy>
57 {
58 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
59 {
60 T old;
61 auto& ref(*addr);
62// atomically update ref, but capture the original value in old
63# if BOOST_COMP_GNUC
64# pragma GCC diagnostic push
65# pragma GCC diagnostic ignored "-Wconversion"
66# endif
67# pragma omp atomic capture
68 {
69 old = ref;
70 ref -= value;
71 }
72# if BOOST_COMP_GNUC
73# pragma GCC diagnostic pop
74# endif
75 return old;
76 }
77 };
78
79 //! The OpenMP accelerators atomic operation: EXCH
80 template<typename T, typename THierarchy>
81 struct AtomicOp<AtomicExch, AtomicOmpBuiltIn, T, THierarchy>
82 {
83 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
84 {
85 T old;
86 auto& ref(*addr);
87// atomically update ref, but capture the original value in old
88# pragma omp atomic capture
89 {
90 old = ref;
91 ref = value;
92 }
93 return old;
94 }
95 };
96
97 //! The OpenMP accelerators atomic operation: AND
98 template<typename T, typename THierarchy>
99 struct AtomicOp<AtomicAnd, AtomicOmpBuiltIn, T, THierarchy>
100 {
101 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
102 {
103 T old;
104 auto& ref(*addr);
105// atomically update ref, but capture the original value in old
106# if BOOST_COMP_GNUC
107# pragma GCC diagnostic push
108# pragma GCC diagnostic ignored "-Wconversion"
109# endif
110# pragma omp atomic capture
111 {
112 old = ref;
113 ref &= value;
114 }
115# if BOOST_COMP_GNUC
116# pragma GCC diagnostic pop
117# endif
118 return old;
119 }
120 };
121
122 //! The OpenMP accelerators atomic operation: OR
123 template<typename T, typename THierarchy>
124 struct AtomicOp<AtomicOr, AtomicOmpBuiltIn, T, THierarchy>
125 {
126 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
127 {
128 T old;
129 auto& ref(*addr);
130// atomically update ref, but capture the original value in old
131# if BOOST_COMP_GNUC
132# pragma GCC diagnostic push
133# pragma GCC diagnostic ignored "-Wconversion"
134# endif
135# pragma omp atomic capture
136 {
137 old = ref;
138 ref |= value;
139 }
140# if BOOST_COMP_GNUC
141# pragma GCC diagnostic pop
142# endif
143 return old;
144 }
145 };
146
147 //! The OpenMP accelerators atomic operation: XOR
148 template<typename T, typename THierarchy>
149 struct AtomicOp<AtomicXor, AtomicOmpBuiltIn, T, THierarchy>
150 {
151 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
152 {
153 T old;
154 auto& ref(*addr);
155// atomically update ref, but capture the original value in old
156# if BOOST_COMP_GNUC
157# pragma GCC diagnostic push
158# pragma GCC diagnostic ignored "-Wconversion"
159# endif
160# pragma omp atomic capture
161 {
162 old = ref;
163 ref ^= value;
164 }
165# if BOOST_COMP_GNUC
166# pragma GCC diagnostic pop
167# endif
168 return old;
169 }
170 };
171
172# endif // _OPENMP >= 201107
173
174// check for OpenMP 5.1+
175// "omp atomic compare" was introduced with OpenMP 5.1
176# if _OPENMP >= 202011
177
178 //! The OpenMP accelerators atomic operation: Min
179 template<typename T, typename THierarchy>
180 struct AtomicOp<AtomicMin, AtomicOmpBuiltIn, T, THierarchy>
181 {
182 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T value) -> T
183 {
184 T old;
185 auto& ref(*addr);
186// atomically update ref, but capture the original value in old
187# pragma omp atomic capture compare
188 {
189 old = ref;
190 // Do not remove the curly brackets of the if body else
191 // icpx 2024.0 is not able to compile the atomics.
192 if(value < ref)
193 {
194 ref = value;
195 }
196 }
197 return old;
198 }
199 };
200
201 //! The OpenMP accelerators atomic operation: Max
202 template<typename T, typename THierarchy>
203 struct AtomicOp<AtomicMax, AtomicOmpBuiltIn, T, THierarchy>
204 {
205 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T value) -> T
206 {
207 T old;
208 auto& ref(*addr);
209// atomically update ref, but capture the original value in old
210# pragma omp atomic capture compare
211 {
212 old = ref;
213 // Do not remove the curly brackets of the if body else
214 // icpx 2024.0 is not able to compile the atomics.
215 if(value > ref)
216 {
217 ref = value;
218 }
219 }
220 return old;
221 }
222 };
223
224 //! The OpenMP accelerators atomic operation: Inc
225 template<typename T, typename THierarchy>
226 struct AtomicOp<AtomicInc, AtomicOmpBuiltIn, T, THierarchy>
227 {
228 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
229 {
230 // TODO(bgruber): atomic increment with wrap around is not implementable in OpenMP 5.1
231 T old;
232# pragma omp critical(AlpakaOmpAtomicOp)
233 {
234 old = AtomicInc{}(addr, value);
235 }
236 return old;
237 }
238 };
239
240 //! The OpenMP accelerators atomic operation: Dec
241 template<typename T, typename THierarchy>
242 struct AtomicOp<AtomicDec, AtomicOmpBuiltIn, T, THierarchy>
243 {
244 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
245 {
246 // TODO(bgruber): atomic decrement with wrap around is not implementable in OpenMP 5.1
247 T old;
248# pragma omp critical(AlpakaOmpAtomicOp)
249 {
250 old = AtomicDec{}(addr, value);
251 }
252 return old;
253 }
254 };
255
256 //! The OpenMP accelerators atomic operation: Cas
257 template<typename T, typename THierarchy>
258 struct AtomicOp<AtomicCas, AtomicOmpBuiltIn, T, THierarchy>
259 {
260 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T compare, T value) -> T
261 {
262 T old;
263 auto& ref(*addr);
264// atomically update ref, but capture the original value in old
265# pragma omp atomic capture compare
266 {
267 old = ref;
268 // Do not remove the curly brackets of the if body else
269 // icpx 2024.0 is not able to compile the atomics.
270 if(ref == compare)
271 {
272 ref = value;
273 }
274 }
275 return old;
276 }
277 };
278
279# else
280 //! The OpenMP accelerators atomic operation
281 //
282 // generic implementations for operations where native atomics are not available
283 template<typename TOp, typename T, typename THierarchy>
284 struct AtomicOp<TOp, AtomicOmpBuiltIn, T, THierarchy>
285 {
286 ALPAKA_FN_HOST static auto atomicOp(AtomicOmpBuiltIn const&, T* const addr, T const& value) -> T
287 {
288 T old;
289 // \TODO: Currently not only the access to the same memory location is protected by a mutex but all
290 // atomic ops on all threads.
291# pragma omp critical(AlpakaOmpAtomicOp)
292 {
293 old = TOp()(addr, value);
294 }
295 return old;
296 }
297
298 ALPAKA_FN_HOST static auto atomicOp(
299 AtomicOmpBuiltIn const&,
300 T* const addr,
301 T const& compare,
302 T const& value) -> T
303 {
304 T old;
305 // \TODO: Currently not only the access to the same memory location is protected by a mutex but all
306 // atomic ops on all threads.
307# pragma omp critical(AlpakaOmpAtomicOp2)
308 {
309 old = TOp()(addr, compare, value);
310 }
311 return old;
312 }
313 };
314
315# endif // _OPENMP >= 202011
316
317 } // namespace trait
318} // namespace alpaka
319
320#endif
The OpenMP accelerators atomic ops.
#define ALPAKA_FN_HOST
Definition Common.hpp:40
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.
Definition Traits.hpp:73
The addition function object.
Definition Op.hpp:17