alpaka
Abstraction Library for Parallel Kernel Acceleration
Op.hpp
Go to the documentation of this file.
1 /* Copyright 2020 Benjamin Worpitz, Bernhard Manfred Gruber
2  * SPDX-License-Identifier: MPL-2.0
3  */
4 
5 #pragma once
6 
8 #include "alpaka/core/Common.hpp"
9 
10 #include <algorithm>
11 #include <type_traits>
12 
13 namespace alpaka
14 {
15  //! The addition function object.
16  struct AtomicAdd
17  {
18  //! \return The old value of addr.
20  template<typename T>
21  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
22  {
23  auto const old = *addr;
24  auto& ref = *addr;
25 #if BOOST_COMP_GNUC
26 # pragma GCC diagnostic push
27 # pragma GCC diagnostic ignored "-Wconversion"
28 #endif
29  ref += value;
30  return old;
31 #if BOOST_COMP_GNUC
32 # pragma GCC diagnostic pop
33 #endif
34  }
35  };
36 
37  //! The subtraction function object.
38  struct AtomicSub
39  {
40  //! \return The old value of addr.
42  template<typename T>
43  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
44  {
45  auto const old = *addr;
46  auto& ref = *addr;
47 #if BOOST_COMP_GNUC
48 # pragma GCC diagnostic push
49 # pragma GCC diagnostic ignored "-Wconversion"
50 #endif
51  ref -= value;
52 #if BOOST_COMP_GNUC
53 # pragma GCC diagnostic pop
54 #endif
55  return old;
56  }
57  };
58 
59  //! The minimum function object.
60  struct AtomicMin
61  {
62  //! \return The old value of addr.
64  template<typename T>
65  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
66  {
67  auto const old = *addr;
68  auto& ref = *addr;
69  ref = std::min(ref, value);
70  return old;
71  }
72  };
73 
74  //! The maximum function object.
75  struct AtomicMax
76  {
77  //! \return The old value of addr.
79  template<typename T>
80  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
81  {
82  auto const old = *addr;
83  auto& ref = *addr;
84  ref = std::max(ref, value);
85  return old;
86  }
87  };
88 
89  //! The exchange function object.
90  struct AtomicExch
91  {
92  //! \return The old value of addr.
94  template<typename T>
95  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
96  {
97  auto const old = *addr;
98  auto& ref = *addr;
99  ref = value;
100  return old;
101  }
102  };
103 
104  //! The increment function object.
105  struct AtomicInc
106  {
107  //! Increments up to value, then reset to 0.
108  //!
109  //! \return The old value of addr.
111  template<typename T>
112  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
113  {
114  auto const old = *addr;
115  auto& ref = *addr;
116  ref = ((old >= value) ? static_cast<T>(0) : static_cast<T>(old + static_cast<T>(1)));
117  return old;
118  }
119  };
120 
121  //! The decrement function object.
122  struct AtomicDec
123  {
124  //! Decrement down to 0, then reset to value.
125  //!
126  //! \return The old value of addr.
128  template<typename T>
129  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
130  {
131  auto const old = *addr;
132  auto& ref = *addr;
133  ref = (((old == static_cast<T>(0)) || (old > value)) ? value : static_cast<T>(old - static_cast<T>(1)));
134  return old;
135  }
136  };
137 
138  //! The and function object.
139  struct AtomicAnd
140  {
141  //! \return The old value of addr.
143  template<typename T>
144  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
145  {
146  auto const old = *addr;
147  auto& ref = *addr;
148  ref &= value;
149  return old;
150  }
151  };
152 
153  //! The or function object.
154  struct AtomicOr
155  {
156  //! \return The old value of addr.
158  template<typename T>
159  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
160  {
161  auto const old = *addr;
162  auto& ref = *addr;
163  ref |= value;
164  return old;
165  }
166  };
167 
168  //! The exclusive or function object.
169  struct AtomicXor
170  {
171  //! \return The old value of addr.
173  template<typename T>
174  ALPAKA_FN_HOST_ACC auto operator()(T* const addr, T const& value) const -> T
175  {
176  auto const old = *addr;
177  auto& ref = *addr;
178  ref ^= value;
179  return old;
180  }
181  };
182 
183  //! The compare and swap function object.
184  struct AtomicCas
185  {
186  //! AtomicCas for non floating point values
187  // \return The old value of addr.
189  template<typename T, std::enable_if_t<!std::is_floating_point_v<T>, bool> = true>
190  ALPAKA_FN_HOST_ACC auto operator()(T* addr, T const& compare, T const& value) const -> T
191  {
192  auto const old = *addr;
193  auto& ref = *addr;
194 
195 // gcc-7.4.0 assumes for an optimization that a signed overflow does not occur here.
196 // That's fine, so ignore that warning.
197 #if BOOST_COMP_GNUC && (BOOST_COMP_GNUC == BOOST_VERSION_NUMBER(7, 4, 0))
198 # pragma GCC diagnostic push
199 # pragma GCC diagnostic ignored "-Wstrict-overflow"
200 #endif
201  // check if values are bit-wise equal
202  ref = ((old == compare) ? value : old);
203 #if BOOST_COMP_GNUC && (BOOST_COMP_GNUC == BOOST_VERSION_NUMBER(7, 4, 0))
204 # pragma GCC diagnostic pop
205 #endif
206  return old;
207  }
208 
209  //! AtomicCas for floating point values
210  // \return The old value of addr.
212  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
213  ALPAKA_FN_HOST_ACC auto operator()(T* addr, T const& compare, T const& value) const -> T
214  {
215  static_assert(sizeof(T) == 4u || sizeof(T) == 8u, "AtomicCas is supporting only 32bit and 64bit values!");
216  // Type to reinterpret too to perform the bit comparison
217  using BitType = std::conditional_t<sizeof(T) == 4u, unsigned int, unsigned long long>;
218 
219  // type used to have a safe way to reinterprete the data into another type
220  // std::variant can not be used because clang8 has issues to compile std::variant
221  struct BitUnion
222  {
223  union
224  {
225  T value;
226  BitType r;
227  };
228  };
229 
230  auto const old = *addr;
231  auto& ref = *addr;
232 
233 // gcc-7.4.0 assumes for an optimization that a signed overflow does not occur here.
234 // That's fine, so ignore that warning.
235 #if BOOST_COMP_GNUC && (BOOST_COMP_GNUC == BOOST_VERSION_NUMBER(7, 4, 0))
236 # pragma GCC diagnostic push
237 # pragma GCC diagnostic ignored "-Wstrict-overflow"
238 #endif
239  BitUnion o{old};
240  BitUnion c{compare};
241 
242  ref = ((o.r == c.r) ? value : old);
243 #if BOOST_COMP_GNUC && (BOOST_COMP_GNUC == BOOST_VERSION_NUMBER(7, 4, 0))
244 # pragma GCC diagnostic pop
245 #endif
246  return old;
247  }
248  };
249 } // namespace alpaka
#define ALPAKA_FN_HOST_ACC
Definition: Common.hpp:39
#define ALPAKA_NO_HOST_ACC_WARNING
Disable nvcc warning: 'calling a host function from host device function.' Usage: ALPAKA_NO_HOST_ACC_...
Definition: Common.hpp:82
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto max(T const &max_ctx, Tx const &x, Ty const &y)
Returns the larger of two arguments. NaNs are treated as missing data (between a NaN and a numeric va...
Definition: Traits.hpp:1263
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto min(T const &min_ctx, Tx const &x, Ty const &y)
Returns the smaller of two arguments. NaNs are treated as missing data (between a NaN and a numeric v...
Definition: Traits.hpp:1280
The alpaka accelerator library.
The addition function object.
Definition: Op.hpp:17
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:21
The and function object.
Definition: Op.hpp:140
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:144
The compare and swap function object.
Definition: Op.hpp:185
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *addr, T const &compare, T const &value) const -> T
AtomicCas for non floating point values.
Definition: Op.hpp:190
The decrement function object.
Definition: Op.hpp:123
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Decrement down to 0, then reset to value.
Definition: Op.hpp:129
The exchange function object.
Definition: Op.hpp:91
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:95
The increment function object.
Definition: Op.hpp:106
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Increments up to value, then reset to 0.
Definition: Op.hpp:112
The maximum function object.
Definition: Op.hpp:76
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:80
The minimum function object.
Definition: Op.hpp:61
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:65
The or function object.
Definition: Op.hpp:155
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:159
The subtraction function object.
Definition: Op.hpp:39
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:43
The exclusive or function object.
Definition: Op.hpp:170
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto operator()(T *const addr, T const &value) const -> T
Definition: Op.hpp:174