DASH  0.3.0
Reduce.h
1 #ifndef DASH__ALGORITHM__REDUCE_H__
2 #define DASH__ALGORITHM__REDUCE_H__
3 
4 #include <dash/iterator/GlobIter.h>
5 #include <dash/iterator/IteratorTraits.h>
6 
7 #include <dash/algorithm/LocalRange.h>
8 #include <dash/algorithm/Operation.h>
9 
10 
11 namespace dash {
12 
13 namespace internal {
14 
15  template<typename ValueType>
16  struct local_result {
17  ValueType value{};
18  bool valid = false;
19  };
20 
21  template<typename ValueType, typename F>
22  void reduce_custom_fn(
23  const void *invec,
24  void *inoutvec,
25  size_t,
26  void *userdata)
27  {
28  using local_result_t = struct local_result<ValueType>;
29  const auto* in = static_cast<const local_result_t*>(invec);
30  auto* inout = static_cast<local_result_t*>(inoutvec);
31  F& fn = *static_cast<F*>(userdata);
32  if (in->valid) {
33  if (inout->valid) {
34  inout->value = fn(in->value, inout->value);
35  } else {
36  inout->value = in->value;
37  inout->valid = true;
38  }
39  }
40  }
41 } // namespace internal
42 
43 
70 template <
71  class LocalInputIter,
72  class InitType,
73  class BinaryOperation
75  typename = typename std::enable_if<
76  !dash::detail::is_global_iterator<LocalInputIter>::value
77  >::type>
78 typename std::iterator_traits<LocalInputIter>::value_type
80  LocalInputIter in_first,
81  LocalInputIter in_last,
82  InitType init,
83  BinaryOperation binary_op = BinaryOperation(),
84  bool non_empty = true,
85  dash::Team & team = dash::Team::All())
86 {
87  using value_t = typename std::iterator_traits<LocalInputIter>::value_type;
88  using local_result_t = struct dash::internal::local_result<value_t>;
89  auto myid = team.myid();
90  auto l_first = in_first;
91  auto l_last = in_last;
92 
93  local_result_t l_result;
94  local_result_t g_result;
95  if (l_first != l_last) {
96  l_result.value = std::accumulate(std::next(l_first),
97  l_last, *l_first,
98  binary_op);
99  l_result.valid = true;
100  }
101  dart_operation_t dop =
102  dash::internal::dart_reduce_operation<BinaryOperation>::value;
104 
105  if (!non_empty || dop == DART_OP_UNDEFINED || dtype == DART_TYPE_UNDEFINED)
106  {
107  dart_type_create_custom(sizeof(local_result_t), &dtype);
108 
109  // we need a custom reduction operation because not every unit
110  // may have valid values
112  &dash::internal::reduce_custom_fn<value_t, BinaryOperation>,
113  &binary_op, true, dtype, true, &dop);
114  dart_allreduce(&l_result, &g_result, 1, dtype, dop, team.dart_id());
115  dart_op_destroy(&dop);
116  dart_type_destroy(&dtype);
117  } else {
118  // ideal case: we can use DART predefined reductions
119  dart_allreduce(&l_result.value, &g_result.value, 1, dtype, dop, team.dart_id());
120  g_result.valid = true;
121  }
122  if (!g_result.valid) {
123  DASH_LOG_ERROR("dash::reduce()", "Found invalid reduction value!");
124  }
125  auto result = g_result.value;
126 
127  result = binary_op(init, result);
128 
129  return result;
130 }
131 
155 template <
156  class LocalInputIter,
157  class InitType = typename std::iterator_traits<LocalInputIter>::value_type,
158  typename = typename std::enable_if<
159  !dash::detail::is_global_iterator<LocalInputIter>::value
160  >::type>
161 typename std::iterator_traits<LocalInputIter>::value_type
163  LocalInputIter in_first,
164  LocalInputIter in_last,
165  InitType init,
166  bool non_empty,
167  dash::Team & team = dash::Team::All())
168 {
169  using value_t = typename std::iterator_traits<LocalInputIter>::value_type;
170  return dash::reduce(
171  in_first,
172  in_last,
173  init,
175  non_empty,
176  team);
177 }
178 
203 template <
204  class GlobInputIt,
205  class InitType = typename dash::iterator_traits<GlobInputIt>::value_type,
206  class BinaryOperation
208  typename = typename std::enable_if<
209  dash::detail::is_global_iterator<GlobInputIt>::value
210  >::type>
211 typename dash::iterator_traits<GlobInputIt>::value_type
213  GlobInputIt in_first,
214  GlobInputIt in_last,
215  InitType init,
216  BinaryOperation binary_op = BinaryOperation())
217 {
218  auto & team = in_first.team();
219  auto index_range = dash::local_range(in_first, in_last);
220  auto l_first = index_range.begin;
221  auto l_last = index_range.end;
222 
223  // TODO: can we figure out whether or not units are empty?
224  static constexpr bool units_non_empty = false;
225  return dash::reduce(l_first,
226  l_last,
227  init,
228  binary_op,
229  units_non_empty,
230  team);
231 }
232 
233 } // namespace dash
234 
235 #endif // DASH__ALGORITHM__REDUCE_H__
global_unit_t myid()
Shortcut to query the global unit ID of the calling unit.
Reduce operands to their sum.
Definition: Operation.h:163
std::iterator_traits< LocalInputIter >::value_type reduce(LocalInputIter in_first, LocalInputIter in_last, InitType init, BinaryOperation binary_op=BinaryOperation(), bool non_empty=true, dash::Team &team=dash::Team::All())
Accumulate values in each process&#39; range [in_first, in_last) using the provided binary reduce functio...
Definition: Reduce.h:79
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
dart_ret_t dart_op_destroy(dart_operation_t *op)
Destroy a operation object created through dart_op_create and set op to DART_OP_UNDEFINED.
LocalRange< const typename GlobIterType::value_type > local_range(const GlobIterType &first, const GlobIterType &last)
Resolves the local address range between global iterators.
Definition: LocalRange.h:295
intptr_t dart_datatype_t
Raw data types supported by the DART interface.
Definition: dart_types.h:121
dart_ret_t dart_type_destroy(dart_datatype_t *dart_type)
Destroy a data type that was previously created using dart_type_create_strided or dart_type_create_in...
dart_ret_t dart_allreduce(const void *sendbuf, void *recvbuf, size_t nelem, dart_datatype_t dtype, dart_operation_t op, dart_team_t team)
DART Equivalent to MPI allreduce.
A Team instance specifies a subset of all available units.
Definition: Team.h:41
Allow input operations on the stream.
dart_ret_t dart_type_create_custom(size_t num_bytes, dart_datatype_t *newtype)
Create a custom data type of size num_bytes bytes.
Undefined, do not use.
Definition: dart_types.h:71
struct dash::dart_operation ValueType
Reduce operands to their minimum value.
Convencience wrapper to determine the DART type and number of elements required for the given templat...
Definition: Types.h:295
static Team & All()
The invariant Team instance containing all available units.
Definition: Team.h:213
void init(int *argc, char ***argv)
Initialize the DASH library and the underlying runtime system.
dart_ret_t dart_op_create(dart_operator_t op, void *userdata, bool commute, dart_datatype_t dtype, bool dtype_is_tmp, dart_operation_t *new_op)
Create a new operation new_op that can be used in collective reduction operations, i.e., dart_reduce, dart_allreduce.