Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Reduction.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 #ifndef GALOIS_REDUCTION_H
21 #define GALOIS_REDUCTION_H
22 
23 #include <functional>
24 #include <limits>
25 
26 #include "galois/config.h"
28 
29 namespace galois {
30 
64 template <typename T, typename MergeFunc, typename IdFunc>
65 class Reducible : public MergeFunc, public IdFunc {
66 
68 
69  void merge(T& lhs, T&& rhs) {
70  T v{std::move(MergeFunc::operator()(lhs, std::move(rhs)))};
71  lhs = std::move(v);
72  }
73 
74  void merge(T& lhs, const T& rhs) { lhs = MergeFunc::operator()(lhs, rhs); }
75 
76 public:
77  using value_type = T;
78 
79  Reducible(MergeFunc merge_func, IdFunc id_func)
80  : MergeFunc(merge_func), IdFunc(id_func) {
81  for (unsigned i = 0; i < data_.size(); ++i) {
82  *(data_.getRemote(i)) = IdFunc::operator()();
83  }
84  }
85 
90  void update(T&& rhs) { merge(*data_.getLocal(), std::move(rhs)); }
91 
92  void update(const T& rhs) { merge(*data_.getLocal(), rhs); }
93 
97  T& getLocal() { return *data_.getLocal(); }
98 
102  T& reduce() {
103  T& lhs = *data_.getLocal();
104  for (unsigned int i = 1; i < data_.size(); ++i) {
105  T& rhs = *data_.getRemote(i);
106  merge(lhs, std::move(rhs));
107  rhs = IdFunc::operator()();
108  }
109 
110  return lhs;
111  }
112 
113  void reset() {
114  for (unsigned int i = 0; i < data_.size(); ++i) {
115  *data_.getRemote(i) = IdFunc::operator()();
116  }
117  }
118 };
119 
124 template <typename MergeFn, typename IdFn>
125 auto make_reducible(const MergeFn& mergeFn, const IdFn& idFn) {
126  return Reducible<std::invoke_result_t<IdFn>, MergeFn, IdFn>(mergeFn, idFn);
127 }
128 
130 template <typename T>
131 struct gmax {
132  constexpr T operator()(const T& lhs, const T& rhs) const {
133  return std::max<T>(lhs, rhs);
134  }
135 };
136 
138 template <typename T>
139 struct gmin {
140  constexpr T operator()(const T& lhs, const T& rhs) const {
141  return std::min<T>(lhs, rhs);
142  }
143 };
144 
145 template <typename T, T value>
147  constexpr T operator()() const { return T{value}; }
148 };
149 
150 // The following identity_value specializations exist because floating point
151 // numbers cannot be template arguments.
152 
153 template <typename T>
155  constexpr T operator()() const { return T{0}; }
156 };
157 
158 template <typename T>
160  constexpr T operator()() const { return std::numeric_limits<T>::min(); }
161 };
162 
163 template <typename T>
165  constexpr T operator()() const { return std::numeric_limits<T>::max(); }
166 };
167 
169 template <typename T>
170 class GAccumulator : public Reducible<T, std::plus<T>, identity_value_zero<T>> {
172 
173 public:
174  GAccumulator() : base_type(std::plus<T>(), identity_value_zero<T>()) {}
175 
176  GAccumulator& operator+=(const T& rhs) {
177  base_type::update(rhs);
178  return *this;
179  }
180 
181  GAccumulator& operator-=(const T& rhs) {
182  base_type::update(rhs);
183  return *this;
184  }
185 };
186 
188 template <typename T>
189 class GReduceMax : public Reducible<T, gmax<T>, identity_value_min<T>> {
191 
192 public:
194 };
195 
197 template <typename T>
198 class GReduceMin : public Reducible<T, gmin<T>, identity_value_max<T>> {
200 
201 public:
203 };
204 
206 class GReduceLogicalAnd : public Reducible<bool, std::logical_and<bool>,
207  identity_value<bool, true>> {
208  using base_type =
210 
211 public:
213  : base_type(std::logical_and<bool>(), identity_value<bool, true>()) {}
214 };
215 
217 class GReduceLogicalOr : public Reducible<bool, std::logical_or<bool>,
218  identity_value<bool, false>> {
219  using base_type =
221 
222 public:
224  : base_type(std::logical_or<bool>(), identity_value<bool, false>()) {}
225 };
226 
227 } // namespace galois
228 #endif // GALOIS_REDUCTION_H
constexpr T operator()() const
Definition: Reduction.h:155
GAccumulator & operator+=(const T &rhs)
Definition: Reduction.h:176
void reset()
Definition: Reduction.h:113
constexpr T operator()(const T &lhs, const T &rhs) const
Definition: Reduction.h:132
constexpr T operator()() const
Definition: Reduction.h:147
constexpr T operator()() const
Definition: Reduction.h:160
GReduceLogicalAnd()
Definition: Reduction.h:212
Definition: Reduction.h:159
Accumulator for T where accumulation is plus.
Definition: Reduction.h:170
GReduceMin()
Definition: Reduction.h:202
A Reducible stores per-thread values of a variable of type T and merges multiple values into one...
Definition: Reduction.h:65
Accumulator for T where accumulation is max.
Definition: Reduction.h:189
T & getLocal()
Returns a reference to the local value of T.
Definition: Reduction.h:97
const Ty max(std::atomic< Ty > &a, const Ty &b)
Definition: AtomicHelpers.h:40
Definition: PerThreadStorage.h:88
void update(const T &rhs)
Definition: Reduction.h:92
gmax is the functional form of std::max
Definition: Reduction.h:139
GReduceMax()
Definition: Reduction.h:193
Accumulator for T where accumulation is min.
Definition: Reduction.h:198
auto make_reducible(const MergeFn &mergeFn, const IdFn &idFn)
make_reducible creates a Reducible from a merge function and identity function.
Definition: Reduction.h:125
GReduceLogicalOr()
Definition: Reduction.h:223
GAccumulator()
Definition: Reduction.h:174
void operator()(void)
Definition: Executor_ParaMeter.h:417
Definition: Reduction.h:164
gmax is the functional form of std::max
Definition: Reduction.h:131
const Ty min(std::atomic< Ty > &a, const Ty &b)
Definition: AtomicHelpers.h:70
Definition: Reduction.h:146
Definition: Reduction.h:154
T & reduce()
Returns the final reduction value.
Definition: Reduction.h:102
constexpr T operator()(const T &lhs, const T &rhs) const
Definition: Reduction.h:140
logical OR reduction
Definition: Reduction.h:217
void update(T &&rhs)
Updates the thread local value by applying the reduction operator to current and newly provided value...
Definition: Reduction.h:90
constexpr T operator()() const
Definition: Reduction.h:165
GAccumulator & operator-=(const T &rhs)
Definition: Reduction.h:181
Reducible(MergeFunc merge_func, IdFunc id_func)
Definition: Reduction.h:79
logical AND reduction
Definition: Reduction.h:206