alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
AtomicAtomicRef.hpp
Go to the documentation of this file.
1/* Copyright 2022 Felice Pantaleo, Andrea Bocci, Jan Stephan
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
9
10#include <array>
11#include <atomic>
12#include <type_traits>
13
14#ifndef ALPAKA_DISABLE_ATOMIC_ATOMICREF
15# ifndef ALPAKA_HAS_STD_ATOMIC_REF
16# include <boost/atomic.hpp>
17# endif
18
19namespace alpaka
20{
21 namespace detail
22 {
23# if defined(ALPAKA_HAS_STD_ATOMIC_REF)
24 template<typename T>
25 using atomic_ref = std::atomic_ref<T>;
26# else
27 template<typename T>
28 using atomic_ref = boost::atomic_ref<T>;
29# endif
30 } // namespace detail
31
32 //! The atomic ops based on atomic_ref for CPU accelerators.
33 //
34 // Atomics can be used in the grids, blocks and threads hierarchy levels.
35 //
36
38 {
39 };
40
41 template<typename T>
43 {
44 static_assert(
45 std::is_trivially_copyable_v<T> && alpaka::detail::atomic_ref<T>::required_alignment <= alignof(T),
46 "Type not supported by AtomicAtomicRef, please recompile defining "
47 "ALPAKA_DISABLE_ATOMIC_ATOMICREF.");
48 }
49
50 namespace trait
51 {
52 //! The CPU accelerators AtomicAdd.
53 template<typename T, typename THierarchy>
54 struct AtomicOp<AtomicAdd, AtomicAtomicRef, T, THierarchy>
55 {
56 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
57 {
58 isSupportedByAtomicAtomicRef<T>();
60 return ref.fetch_add(value);
61 }
62 };
63
64 //! The CPU accelerators AtomicSub.
65 template<typename T, typename THierarchy>
66 struct AtomicOp<AtomicSub, AtomicAtomicRef, T, THierarchy>
67 {
68 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
69 {
70 isSupportedByAtomicAtomicRef<T>();
72 return ref.fetch_sub(value);
73 }
74 };
75
76 //! The CPU accelerators AtomicMin.
77 template<typename T, typename THierarchy>
78 struct AtomicOp<AtomicMin, AtomicAtomicRef, T, THierarchy>
79 {
80 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
81 {
82 isSupportedByAtomicAtomicRef<T>();
84 T old = ref;
85 T result = old;
86 result = std::min(result, value);
87 while(!ref.compare_exchange_weak(old, result))
88 {
89 result = old;
90 result = std::min(result, value);
91 }
92 return old;
93 }
94 };
95
96 //! The CPU accelerators AtomicMax.
97 template<typename T, typename THierarchy>
98 struct AtomicOp<AtomicMax, AtomicAtomicRef, T, THierarchy>
99 {
100 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
101 {
102 isSupportedByAtomicAtomicRef<T>();
104 T old = ref;
105 T result = old;
106 result = std::max(result, value);
107 while(!ref.compare_exchange_weak(old, result))
108 {
109 result = old;
110 result = std::max(result, value);
111 }
112 return old;
113 }
114 };
115
116 //! The CPU accelerators AtomicExch.
117 template<typename T, typename THierarchy>
118 struct AtomicOp<AtomicExch, AtomicAtomicRef, T, THierarchy>
119 {
120 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
121 {
122 isSupportedByAtomicAtomicRef<T>();
124 T old = ref;
125 T result = value;
126 while(!ref.compare_exchange_weak(old, result))
127 {
128 result = value;
129 }
130 return old;
131 }
132 };
133
134 //! The CPU accelerators AtomicInc.
135 template<typename T, typename THierarchy>
136 struct AtomicOp<AtomicInc, AtomicAtomicRef, T, THierarchy>
137 {
138 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
139 {
140 isSupportedByAtomicAtomicRef<T>();
142 T old = ref;
143 T result = ((old >= value) ? 0 : static_cast<T>(old + 1));
144 while(!ref.compare_exchange_weak(old, result))
145 {
146 result = ((old >= value) ? 0 : static_cast<T>(old + 1));
147 }
148 return old;
149 }
150 };
151
152 //! The CPU accelerators AtomicDec.
153 template<typename T, typename THierarchy>
154 struct AtomicOp<AtomicDec, AtomicAtomicRef, T, THierarchy>
155 {
156 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
157 {
158 isSupportedByAtomicAtomicRef<T>();
160 T old = ref;
161 T result = ((old >= value) ? 0 : static_cast<T>(old - 1));
162 while(!ref.compare_exchange_weak(old, result))
163 {
164 result = ((old >= value) ? 0 : static_cast<T>(old - 1));
165 }
166 return old;
167 }
168 };
169
170 //! The CPU accelerators AtomicAnd.
171 template<typename T, typename THierarchy>
172 struct AtomicOp<AtomicAnd, AtomicAtomicRef, T, THierarchy>
173 {
174 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
175 {
176 isSupportedByAtomicAtomicRef<T>();
178 return ref.fetch_and(value);
179 }
180 };
181
182 //! The CPU accelerators AtomicOr.
183 template<typename T, typename THierarchy>
184 struct AtomicOp<AtomicOr, AtomicAtomicRef, T, THierarchy>
185 {
186 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
187 {
188 isSupportedByAtomicAtomicRef<T>();
190 return ref.fetch_or(value);
191 }
192 };
193
194 //! The CPU accelerators AtomicXor.
195 template<typename T, typename THierarchy>
196 struct AtomicOp<AtomicXor, AtomicAtomicRef, T, THierarchy>
197 {
198 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
199 {
200 isSupportedByAtomicAtomicRef<T>();
202 return ref.fetch_xor(value);
203 }
204 };
205
206 //! The CPU accelerators AtomicCas.
207 template<typename T, typename THierarchy>
208 struct AtomicOp<AtomicCas, AtomicAtomicRef, T, THierarchy>
209 {
210 ALPAKA_FN_HOST static auto atomicOp(
211 AtomicAtomicRef const&,
212 T* const addr,
213 T const& compare,
214 T const& value) -> T
215 {
216 isSupportedByAtomicAtomicRef<T>();
218 T old = ref;
219 T result;
220 do
221 {
222# if BOOST_COMP_GNUC || BOOST_COMP_CLANG
223# pragma GCC diagnostic push
224# pragma GCC diagnostic ignored "-Wfloat-equal"
225# endif
226 result = ((old == compare) ? value : old);
227# if BOOST_COMP_GNUC || BOOST_COMP_CLANG
228# pragma GCC diagnostic pop
229# endif
230 } while(!ref.compare_exchange_weak(old, result));
231 return old;
232 }
233 };
234 } // namespace trait
235} // namespace alpaka
236
237#endif
The atomic ops based on atomic_ref for CPU accelerators.
#define ALPAKA_FN_HOST
Definition Common.hpp:40
boost::atomic_ref< T > atomic_ref
The alpaka accelerator library.
void isSupportedByAtomicAtomicRef()
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