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
7#if defined(ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED) || defined(ALPAKA_ACC_CPU_B_SEQ_T_THREADS_ENABLED) \
8 || defined(ALPAKA_ACC_CPU_B_OMP2_T_SEQ_ENABLED) || defined(ALPAKA_ACC_CPU_B_SEQ_T_OMP2_ENABLED) \
9 || defined(ALPAKA_ACC_CPU_B_TBB_T_SEQ_ENABLED)
10
12# include "alpaka/core/Config.hpp"
13
14# include <array>
15# include <atomic>
16# include <type_traits>
17
18# ifndef ALPAKA_DISABLE_ATOMIC_ATOMICREF
19# ifndef ALPAKA_HAS_STD_ATOMIC_REF
20# include <boost/atomic.hpp>
21# endif
22
23namespace alpaka
24{
25 namespace detail
26 {
27# if defined(ALPAKA_HAS_STD_ATOMIC_REF)
28 template<typename T>
29 using atomic_ref = std::atomic_ref<T>;
30# else
31 template<typename T>
32 using atomic_ref = boost::atomic_ref<T>;
33# endif
34 } // namespace detail
35
36 //! The atomic ops based on atomic_ref for CPU accelerators.
37 //
38 // Atomics can be used in the grids, blocks and threads hierarchy levels.
39 //
40
42 {
43 };
44
45 template<typename T>
47 {
48 static_assert(
49 std::is_trivially_copyable_v<T> && alpaka::detail::atomic_ref<T>::required_alignment <= alignof(T),
50 "Type not supported by AtomicAtomicRef, please recompile defining "
51 "ALPAKA_DISABLE_ATOMIC_ATOMICREF.");
52 }
53
54 namespace trait
55 {
56 //! The CPU accelerators AtomicAdd.
57 template<typename T, typename THierarchy>
58 struct AtomicOp<AtomicAdd, AtomicAtomicRef, T, THierarchy>
59 {
60 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
61 {
62 isSupportedByAtomicAtomicRef<T>();
64 return ref.fetch_add(value);
65 }
66 };
67
68 //! The CPU accelerators AtomicSub.
69 template<typename T, typename THierarchy>
70 struct AtomicOp<AtomicSub, AtomicAtomicRef, T, THierarchy>
71 {
72 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
73 {
74 isSupportedByAtomicAtomicRef<T>();
76 return ref.fetch_sub(value);
77 }
78 };
79
80 //! The CPU accelerators AtomicMin.
81 template<typename T, typename THierarchy>
82 struct AtomicOp<AtomicMin, AtomicAtomicRef, T, THierarchy>
83 {
84 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
85 {
86 isSupportedByAtomicAtomicRef<T>();
88 T old = ref;
89 T result = old;
90 result = std::min(result, value);
91 while(!ref.compare_exchange_weak(old, result))
92 {
93 result = old;
94 result = std::min(result, value);
95 }
96 return old;
97 }
98 };
99
100 //! The CPU accelerators AtomicMax.
101 template<typename T, typename THierarchy>
102 struct AtomicOp<AtomicMax, AtomicAtomicRef, T, THierarchy>
103 {
104 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
105 {
106 isSupportedByAtomicAtomicRef<T>();
108 T old = ref;
109 T result = old;
110 result = std::max(result, value);
111 while(!ref.compare_exchange_weak(old, result))
112 {
113 result = old;
114 result = std::max(result, value);
115 }
116 return old;
117 }
118 };
119
120 //! The CPU accelerators AtomicExch.
121 template<typename T, typename THierarchy>
122 struct AtomicOp<AtomicExch, AtomicAtomicRef, T, THierarchy>
123 {
124 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
125 {
126 isSupportedByAtomicAtomicRef<T>();
128 T old = ref;
129 T result = value;
130 while(!ref.compare_exchange_weak(old, result))
131 {
132 result = value;
133 }
134 return old;
135 }
136 };
137
138 //! The CPU accelerators AtomicInc.
139 template<typename T, typename THierarchy>
140 struct AtomicOp<AtomicInc, AtomicAtomicRef, T, THierarchy>
141 {
142 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
143 {
144 isSupportedByAtomicAtomicRef<T>();
146 T old = ref;
147 T result = ((old >= value) ? 0 : static_cast<T>(old + 1));
148 while(!ref.compare_exchange_weak(old, result))
149 {
150 result = ((old >= value) ? 0 : static_cast<T>(old + 1));
151 }
152 return old;
153 }
154 };
155
156 //! The CPU accelerators AtomicDec.
157 template<typename T, typename THierarchy>
158 struct AtomicOp<AtomicDec, AtomicAtomicRef, T, THierarchy>
159 {
160 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
161 {
162 isSupportedByAtomicAtomicRef<T>();
164 T old = ref;
165 T result = ((old >= value) ? 0 : static_cast<T>(old - 1));
166 while(!ref.compare_exchange_weak(old, result))
167 {
168 result = ((old >= value) ? 0 : static_cast<T>(old - 1));
169 }
170 return old;
171 }
172 };
173
174 //! The CPU accelerators AtomicAnd.
175 template<typename T, typename THierarchy>
176 struct AtomicOp<AtomicAnd, AtomicAtomicRef, T, THierarchy>
177 {
178 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
179 {
180 isSupportedByAtomicAtomicRef<T>();
182 return ref.fetch_and(value);
183 }
184 };
185
186 //! The CPU accelerators AtomicOr.
187 template<typename T, typename THierarchy>
188 struct AtomicOp<AtomicOr, AtomicAtomicRef, T, THierarchy>
189 {
190 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
191 {
192 isSupportedByAtomicAtomicRef<T>();
194 return ref.fetch_or(value);
195 }
196 };
197
198 //! The CPU accelerators AtomicXor.
199 template<typename T, typename THierarchy>
200 struct AtomicOp<AtomicXor, AtomicAtomicRef, T, THierarchy>
201 {
202 ALPAKA_FN_HOST static auto atomicOp(AtomicAtomicRef const&, T* const addr, T const& value) -> T
203 {
204 isSupportedByAtomicAtomicRef<T>();
206 return ref.fetch_xor(value);
207 }
208 };
209
210 //! The CPU accelerators AtomicCas.
211 template<typename T, typename THierarchy>
212 struct AtomicOp<AtomicCas, AtomicAtomicRef, T, THierarchy>
213 {
214 ALPAKA_FN_HOST static auto atomicOp(
215 AtomicAtomicRef const&,
216 T* const addr,
217 T const& compare,
218 T const& value) -> T
219 {
220 isSupportedByAtomicAtomicRef<T>();
222 T old = ref;
223 T result;
224 do
225 {
226# if ALPAKA_COMP_GNUC || ALPAKA_COMP_CLANG
227# pragma GCC diagnostic push
228# pragma GCC diagnostic ignored "-Wfloat-equal"
229# endif
230 result = ((old == compare) ? value : old);
231# if ALPAKA_COMP_GNUC || ALPAKA_COMP_CLANG
232# pragma GCC diagnostic pop
233# endif
234 } while(!ref.compare_exchange_weak(old, result));
235 return old;
236 }
237 };
238 } // namespace trait
239} // namespace alpaka
240
241# endif
242#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