alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
atomic.hpp
Go to the documentation of this file.
1/* Copyright 2022 Benjamin Worpitz, René Widera, Bernhard Manfred Gruber
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
7#include "alpaka/api/api.hpp"
10#include "alpaka/onAcc/Acc.hpp"
13#include "alpaka/operation.hpp"
14
15#include <type_traits>
16
17namespace alpaka::onAcc
18{
19 //! Executes the given operation atomically.
20 //!
21 //! \tparam TOp The operation type.
22 //! \tparam T The value type.
23 //! \param addr The value to change atomically.
24 //! \param value The value used in the atomic operation.
25 template<typename TOp, typename T, typename T_Scope = scope::Device>
26 constexpr auto atomicOp(auto const& acc, T* const addr, T const& value, T_Scope const scope = T_Scope()) -> T
27 {
28 static_assert(!std::is_same_v<T_Scope, scope::System>, "System scope is currently not supported.");
29 auto atomicImpl = trait::getAtomicImpl(acc[object::exec], scope);
30 return internalCompute::Atomic::Op<TOp, ALPAKA_TYPEOF(atomicImpl), T, T_Scope>::atomicOp(
31 atomicImpl,
32 addr,
33 value);
34 }
35
36 //! Executes the given operation atomically.
37 //!
38 //! \tparam TOp The operation type.
39 //! \tparam T The value type.
40 //! \param addr The value to change atomically.
41 //! \param compare The comparison value used in the atomic operation.
42 //! \param value The value used in the atomic operation.
43 template<typename TOp, typename T, typename T_Scope = scope::Device>
44 constexpr auto atomicOp(
45 auto const& acc,
46 T* const addr,
47 T const& compare,
48 T const& value,
49 T_Scope const scope = T_Scope()) -> T
50 {
51 static_assert(!std::is_same_v<T_Scope, scope::System>, "System scope is currently not supported.");
52 auto atomicImpl = trait::getAtomicImpl(acc[object::exec], scope);
53 return internalCompute::Atomic::Op<TOp, ALPAKA_TYPEOF(atomicImpl), T, T_Scope>::atomicOp(
54 atomicImpl,
55 addr,
56 compare,
57 value);
58 }
59
60 //! Executes an atomic add operation.
61 //!
62 //! \tparam T The value type.
63 //! \param addr The value to change atomically.
64 //! \param value The value used in the atomic operation.
65 template<typename T, typename T_Scope = scope::Device>
66 constexpr auto atomicAdd(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
67 {
68 return atomicOp<operation::Add>(acc, addr, value, hier);
69 }
70
71 //! Executes an atomic sub operation.
72 //!
73 //! \tparam T The value type.
74 //! \param addr The value to change atomically.
75 //! \param value The value used in the atomic operation.
76 template<typename T, typename T_Scope = scope::Device>
77 constexpr auto atomicSub(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
78 {
79 return atomicOp<operation::Sub>(acc, addr, value, hier);
80 }
81
82 //! Executes an atomic min operation.
83 //!
84 //! \tparam T The value type.
85 //! \param addr The value to change atomically.
86 //! \param value The value used in the atomic operation.
87 template<typename T, typename T_Scope = scope::Device>
88 constexpr auto atomicMin(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
89 {
90 return atomicOp<operation::Min>(acc, addr, value, hier);
91 }
92
93 //! Executes an atomic max operation.
94 //!
95 //! \tparam T The value type.
96 //! \param addr The value to change atomically.
97 //! \param value The value used in the atomic operation.
98 template<typename T, typename T_Scope = scope::Device>
99 constexpr auto atomicMax(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
100 {
101 return atomicOp<operation::Max>(acc, addr, value, hier);
102 }
103
104 //! Executes an atomic exchange operation.
105 //!
106 //! \tparam T The value type.
107 //! \param addr The value to change atomically.
108 //! \param value The value used in the atomic operation.
109 template<typename T, typename T_Scope = scope::Device>
110 constexpr auto atomicExch(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
111 {
112 return atomicOp<operation::Exch>(acc, addr, value, hier);
113 }
114
115 //! Executes an atomic increment operation.
116 //!
117 //! \tparam T The value type.
118 //! \param addr The value to change atomically.
119 //! \param value The value used in the atomic operation.
120 template<typename T, typename T_Scope = scope::Device>
121 constexpr auto atomicInc(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
122 {
123 return atomicOp<operation::Inc>(acc, addr, value, hier);
124 }
125
126 //! Executes an atomic decrement operation.
127 //!
128 //! \tparam T The value type.
129 //! \param addr The value to change atomically.
130 //! \param value The value used in the atomic operation.
131 template<typename T, typename T_Scope = scope::Device>
132 constexpr auto atomicDec(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
133 {
134 return atomicOp<operation::Dec>(acc, addr, value, hier);
135 }
136
137 //! Executes an atomic and operation.
138 //!
139 //! \tparam T The value type.
140 //! \param addr The value to change atomically.
141 //! \param value The value used in the atomic operation.
142 template<typename T, typename T_Scope = scope::Device>
143 constexpr auto atomicAnd(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
144 {
145 return atomicOp<operation::And>(acc, addr, value, hier);
146 }
147
148 //! Executes an atomic or operation.
149 //!
150 //! \tparam T The value type.
151 //! \param addr The value to change atomically.
152 //! \param value The value used in the atomic operation.
153 template<typename T, typename T_Scope = scope::Device>
154 constexpr auto atomicOr(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
155 {
156 return atomicOp<operation::Or>(acc, addr, value, hier);
157 }
158
159 //! Executes an atomic xor operation.
160 //!
161 //! \tparam T The value type.
162 //! \param addr The value to change atomically.
163 //! \param value The value used in the atomic operation.
164 template<typename T, typename T_Scope = scope::Device>
165 constexpr auto atomicXor(auto const& acc, T* const addr, T const& value, T_Scope const hier = T_Scope()) -> T
166 {
167 return atomicOp<operation::Xor>(acc, addr, value, hier);
168 }
169
170 //! Executes an atomic compare-and-swap operation.
171 //!
172 //! \tparam T The value type.
173 //! \param addr The value to change atomically.
174 //! \param compare The comparison value used in the atomic operation.
175 //! \param value The value used in the atomic operation.
176 template<typename T, typename T_Scope = scope::Device>
177 constexpr auto atomicCas(
178 auto const& acc,
179 T* const addr,
180 T const& compare,
181 T const& value,
182 T_Scope const hier = T_Scope()) -> T
183 {
184 return atomicOp<operation::Cas>(acc, addr, compare, value, hier);
185 }
186
187 namespace atomic
188 {
189 /** Defines the equivalent of an atomic invoke for user defined functors.
190 *
191 * This function can be specialized within the namespace of the user functor type and will be found via ADL.
192 * Typically, this functor is used within the reduce and transformReduce algorithm.
193 * The implementation must implement the functor equivalent atomic function.
194 *
195 * @param fn non-atomic user functor
196 * @param inOut pointer to the values which is updated
197 * @param args arguments normally forwarded to the user functor
198 */
199 ALPAKA_FN_ACC void alpakaAtomicInvoke(auto&& fn, concepts::Acc auto const& acc, auto* inOut, auto&&... args)
200 {
201 alpaka::unused(acc, inOut, args...);
202 static_assert(
203 sizeof(ALPAKA_TYPEOF(fn)) && false,
204 "You must specialize alpakaAtomicInvoke() for your functor. Best place the overload in the namespace "
205 "of the "
206 "functor, it will be found by ADL.");
207 }
208
209 template<typename T>
210 ALPAKA_FN_ACC void alpakaAtomicInvoke(std::plus<T>, concepts::Acc auto const& acc, auto* inOut, auto&&... args)
211 {
212 atomicAdd(acc, inOut, ALPAKA_FORWARD(args)...);
213 }
214 } // namespace atomic
215
216} // namespace alpaka::onAcc
#define ALPAKA_FN_ACC
All functions that can be used on an accelerator have to be attributed with ALPAKA_FN_ACC or ALPAKA_F...
Definition common.hpp:31
#define ALPAKA_TYPEOF(...)
Get the type of instance.
Definition common.hpp:154
#define ALPAKA_FORWARD(instance)
Perfectly forward an instance as argument.
Definition common.hpp:148
Concept to check if a type is an accelerator.
Definition Acc.hpp:119
alpaka'S function interface
Definition fn.hpp:38
ALPAKA_FN_ACC void alpakaAtomicInvoke(auto &&fn, concepts::Acc auto const &acc, auto *inOut, auto &&... args)
Defines the equivalent of an atomic invoke for user defined functors.
Definition atomic.hpp:199
constexpr decltype(auto) getAtomicImpl(T_Executor const executor, T_AtomicScope const atomicScope)
Definition trait.hpp:235
functionality which is usable on the accelerator compute device from within a kernel.
Definition executor.hpp:38
constexpr auto atomicAnd(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic and operation.
Definition atomic.hpp:143
constexpr auto atomicOp(auto const &acc, T *const addr, T const &value, T_Scope const scope=T_Scope()) -> T
Executes the given operation atomically.
Definition atomic.hpp:26
constexpr auto atomicCas(auto const &acc, T *const addr, T const &compare, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic compare-and-swap operation.
Definition atomic.hpp:177
constexpr auto atomicXor(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic xor operation.
Definition atomic.hpp:165
constexpr auto atomicAdd(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic add operation.
Definition atomic.hpp:66
constexpr auto atomicSub(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic sub operation.
Definition atomic.hpp:77
constexpr auto atomicExch(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic exchange operation.
Definition atomic.hpp:110
constexpr auto atomicDec(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic decrement operation.
Definition atomic.hpp:132
constexpr auto atomicInc(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic increment operation.
Definition atomic.hpp:121
constexpr auto atomicOr(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic or operation.
Definition atomic.hpp:154
constexpr auto atomicMin(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic min operation.
Definition atomic.hpp:88
constexpr auto atomicMax(auto const &acc, T *const addr, T const &value, T_Scope const hier=T_Scope()) -> T
Executes an atomic max operation.
Definition atomic.hpp:99