CoDiPack  2.2.0
A Code Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
openMPAtomic.hpp
1/*
2 * CoDiPack, a Code Differentiation Package
3 *
4 * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau
5 * Homepage: http://www.scicomp.uni-kl.de
6 * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de)
7 *
8 * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau)
9 *
10 * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi).
11 *
12 * CoDiPack is free software: you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * CoDiPack is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty
19 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * See the GNU General Public License for more details.
22 * You should have received a copy of the GNU
23 * General Public License along with CoDiPack.
24 * If not, see <http://www.gnu.org/licenses/>.
25 *
26 * For other licensing options please contact us.
27 *
28 * Authors:
29 * - SciComp, University of Kaiserslautern-Landau:
30 * - Max Sagebaum
31 * - Johannes Blühdorn
32 * - Former members:
33 * - Tim Albring
34 */
35#pragma once
36
37#include <type_traits>
38
39#include "../../../expressions/activeType.hpp"
40#include "../../../traits/atomicTraits.hpp"
41#include "../../../traits/realTraits.hpp"
42#include "../../../traits/tapeTraits.hpp"
43#include "../atomicInterface.hpp"
44#include "macros.hpp"
45
47namespace codi {
48
60 template<typename T_Type, typename T_Sfinae = void>
61 struct OpenMPAtomicImpl : public AtomicInterface<T_Type, OpenMPAtomicImpl<T_Type, T_Sfinae>> {
62 public:
63 using Type = T_Type;
64
65 OpenMPAtomicImpl() = delete;
66 };
67
68#ifndef DOXYGEN_DISABLE
69
70 // Specialization for arithmetic types.
71 template<typename T_Type>
72 struct OpenMPAtomicImpl<T_Type, typename std::enable_if<std::is_arithmetic<T_Type>::value>::type>
73 : public AtomicInterface<
74 T_Type, OpenMPAtomicImpl<T_Type, typename std::enable_if<std::is_arithmetic<T_Type>::value>::type>> {
75 public:
76 using Type = T_Type;
77 using Base =
78 AtomicInterface<T_Type,
80
81 private:
82 Type value;
83
84 CODI_INLINE void setValue(Type const& newValue) {
85 CODI_OMP_ATOMIC(write)
86 this->value = newValue;
87 }
88
89 CODI_INLINE Type getValue() const {
90 Type result;
91 CODI_OMP_ATOMIC(read)
92 result = this->value;
93 return result;
94 }
95
96 public:
97 CODI_INLINE OpenMPAtomicImpl() : Base(), value() {}
98
99 CODI_INLINE OpenMPAtomicImpl(OpenMPAtomicImpl const& other) : Base() {
100 setValue(other.getValue());
101 }
102
103 CODI_INLINE OpenMPAtomicImpl(Type const& other) : Base() {
104 setValue(other);
105 }
106
108 return operator=(other.getValue());
109 }
110
112 setValue(other);
113 return *this;
114 }
115
117 return operator+=(other.getValue());
118 }
119
120 CODI_INLINE Type operator+=(Type const& other) {
121 Type result;
122 CODI_OMP_ATOMIC(capture) {
123 this->value += other;
124 result = this->value;
125 }
126 return result;
127 }
128
130 Type result;
131 CODI_OMP_ATOMIC(capture)
132 result = ++this->value;
133 return result;
134 }
135
137 Type result;
138 CODI_OMP_ATOMIC(capture)
139 result = this->value++;
140 return result;
141 }
142
144 Type result;
145 CODI_OMP_ATOMIC(capture)
146 result = --this->value;
147 return result;
148 }
149
151 Type result;
152 CODI_OMP_ATOMIC(capture)
153 result = this->value--;
154 return result;
155 }
156
157 CODI_INLINE operator Type() const {
158 return getValue();
159 }
160 };
161
162 // Specialization for forward CoDiPack types. Acts on value and gradient with individual atomic operations.
163 template<typename T_Type>
164 struct OpenMPAtomicImpl<T_Type, TapeTraits::EnableIfForwardTape<typename T_Type::Tape>>
165 : public AtomicInterface<T_Type,
166 OpenMPAtomicImpl<T_Type, TapeTraits::EnableIfForwardTape<typename T_Type::Tape>>>,
167 public T_Type {
168 public:
169 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
170 using Base =
171 AtomicInterface<T_Type, OpenMPAtomicImpl<T_Type, TapeTraits::EnableIfForwardTape<typename T_Type::Tape>>>;
172 using Tape = typename Type::Tape;
173 using Real = typename Type::Real;
174 using Gradient = typename Type::Gradient;
175
176 private:
177 CODI_INLINE void atomicSetValue(Type const& newValue) {
178 OpenMPAtomicImpl<Real>* atomicValue = reinterpret_cast<OpenMPAtomicImpl<Real>*>(&this->value());
179 OpenMPAtomicImpl<Gradient>* atomicGradient = reinterpret_cast<OpenMPAtomicImpl<Gradient>*>(&this->gradient());
180
181 *atomicValue = newValue.value();
182 *atomicGradient = newValue.gradient();
183 }
184
185 CODI_INLINE Type atomicGetValue() const {
186 Type result;
187
188 OpenMPAtomicImpl<Real> const* atomicValue = reinterpret_cast<OpenMPAtomicImpl<Real> const*>(&this->value());
189 OpenMPAtomicImpl<Gradient> const* atomicGradient =
190 reinterpret_cast<OpenMPAtomicImpl<Gradient> const*>(&this->gradient());
191
192 result.value() = *atomicValue;
193 result.gradient() = *atomicGradient;
194
195 return result;
196 }
197
198 public:
199 CODI_INLINE OpenMPAtomicImpl() : Base(), Type() {}
200
201 CODI_INLINE OpenMPAtomicImpl(OpenMPAtomicImpl const& other) : Base(), Type() {
202 atomicSetValue(other.atomicGetValue());
203 }
204
205 CODI_INLINE OpenMPAtomicImpl(Type const& other) : Base(), Type() {
206 atomicSetValue(other);
207 }
208
210 return operator=(other.atomicGetValue());
211 }
212
214 atomicSetValue(other);
215 return *this;
216 }
217
219 return operator+=(other.atomicGetValue());
220 }
221
223 OpenMPAtomicImpl<Real>* atomicValue = reinterpret_cast<OpenMPAtomicImpl<Real>*>(&this->value());
224 OpenMPAtomicImpl<Gradient>* atomicGradient = reinterpret_cast<OpenMPAtomicImpl<Gradient>*>(&this->gradient());
225
226 *atomicValue += other.value();
227 *atomicGradient += other.gradient();
228 return *this;
229 }
230
231 CODI_INLINE operator Type() const {
232 return atomicGetValue();
233 }
234 };
235
236#endif
237
240 template<typename Type>
242
244 template<typename T_Type>
245 struct AtomicTraits::IsAtomic<OpenMPAtomic<T_Type>> : std::true_type {};
246
247#ifndef DOXYGEN_DISABLE
248 // Specialize IsTotalZero for OpenMPAtomic on arithmetic types.
249 template<typename T_Type>
251 OpenMPAtomicImpl<T_Type, typename std::enable_if<std::is_arithmetic<T_Type>::value>::type>> {
252 public:
253
254 using Type =
255 CODI_DD(CODI_T(OpenMPAtomicImpl<T_Type, typename std::enable_if<std::is_arithmetic<T_Type>::value>::type>),
257
258 static CODI_INLINE bool isTotalZero(Type const& v) {
259 return typename Type::Type() == v;
260 }
261 };
262#endif
263}
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition: config.h:457
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition: macros.hpp:94
#define CODI_T(...)
Abbreviation for CODI_TEMPLATE.
Definition: macros.hpp:111
void setValue(Type &v, typename DataExtraction< Type >::Real const &value)
Set the primal values of a type of aggregated active types.
Definition: realTraits.hpp:222
DataExtraction< Type >::Real getValue(Type const &v)
Extract the primal values from a type of aggregated active types.
Definition: realTraits.hpp:210
typename std::enable_if< IsForwardTape< Tape >::value >::type EnableIfForwardTape
Enable if wrapper for IsForwardTape.
Definition: tapeTraits.hpp:88
CoDiPack - Code Differentiation Package.
Definition: codi.hpp:90
Represents a concrete lvalue in the CoDiPack expression tree.
Definition: activeType.hpp:52
Provides a data type on which operations are performed atomically.
Definition: atomicInterface.hpp:56
Type operator--()
Pre-decrement operator.
Type operator+=(Impl const &other)
Incremental update with implementing type as rhs.
Impl & operator=(Impl const &other)
Assignment operator with implementing type as rhs.
Type operator++()
Pre-increment operator.
Indicate whether a type is atomic.
Definition: atomicTraits.hpp:51
Atomic implementation for OpenMP.
Definition: openMPAtomic.hpp:61
T_Type Type
See OpenMPAtomicImpl.
Definition: openMPAtomic.hpp:63
OpenMPAtomicImpl()=delete
Constructor is deleted, will throw errors for unspecialized instantiations.
Function for checking if the value of the type is completely zero.
Definition: realTraits.hpp:100
T_Type Type
See IsTotalZero.
Definition: realTraits.hpp:103
static bool isTotalZero(Type const &v)
Checks if the values are completely zero.
Definition: realTraits.hpp:106