ttg 1.0.0
Template Task Graph (TTG): flowgraph-based programming model for high-performance distributed-memory algorithms
Loading...
Searching...
No Matches
reduce.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// Created by Eduard Valeyev on 12/22/17.
4//
5
6#ifndef TTG_REDUCE_H
7#define TTG_REDUCE_H
8
9#include <cassert>
10#include <cstdlib>
11#include <mutex>
12
13#include "ttg/util/tree.h"
14
15namespace ttg {
16
29 template <typename Value, typename BinaryOp, typename OutKey>
31 : public TT<int, std::tuple<Out<int, Value>, Out<int, Value>, Out<int, Value>, Out<OutKey, Value>>,
32 BinaryTreeReduce<Value, BinaryOp, OutKey>, ttg::typelist<Value, Value, Value>> {
33 public:
34 using baseT = typename BinaryTreeReduce::ttT;
35
40 : baseT(edges(fuse(in, inout), inout_l, inout_r), edges(inout, inout_l, inout_r, out), "BinaryTreeReduce",
41 {"in|inout", "inout_l", "inout_r"}, {"inout", "inout_l", "inout_r", "out"}, world, [](int key) { return key; })
42 , tree_((max_key == -1 ? world.size() : max_key), root)
43 , dest_key_(dest_key)
44 , op_(std::move(op)) {
45 init();
46 }
47
48 void op(const int &key, typename baseT::input_values_tuple_type &&indata,
50 assert(key < tree_.size());
51 assert(key == this->get_world().rank());
53 auto children = tree_.child_keys(key);
54 Value result;
55 if (children.first != -1 && children.second != -1)
56 // left-associative in-order reduction: L op This op R = ((L op This) op R)
57 result = op_(op_(baseT::template get<1, Value &&>(indata), baseT::template get<0, Value &&>(indata)),
58 baseT::template get<2, Value &&>(indata));
59 else {
60 if (children.first != -1)
61 result = op_(baseT::template get<1, Value &&>(indata), baseT::template get<0, Value &&>(indata));
62 else if (children.second != -1)
63 result = op_(baseT::template get<0, Value &&>(indata), baseT::template get<2, Value &&>(indata));
64 else
65 result = baseT::template get<0, Value &&>(indata);
66 }
67 auto parent = tree_.parent_key(key);
68 if (parent != -1) {
69 // is this left or right child of the parent?
71 {
73 assert(parents_children.first == key || parents_children.second == key);
74 this_is_left_child = (parents_children.first == key);
75 }
77 send<1>(parent, std::move(result), outdata);
78 else
79 send<2>(parent, std::move(result), outdata);
80 } else
81 send<3>(dest_key_, std::move(result), outdata);
82 }
83
84 private:
86 OutKey dest_key_;
87 BinaryOp op_;
88
91 void init() {
92 // iterate over keys that map to me ... if keys are equivalent to ranks this can be made simpler
93 const auto my_rank = this->get_world().rank();
94 for (auto key = 0; key != tree_.size(); ++key) {
95 if (my_rank == this->get_keymap()(key)) {
96 auto keys = tree_.child_keys(key);
97 if (keys.first == -1) this->template set_arg<1>(key, Value());
98 if (keys.second == -1) this->template set_arg<2>(key, Value());
99 }
100 }
101 }
102 };
103
104#if 0
109template <typename InKey, template Value, template Reducer, template OutKey>
110class Reduce : public TT<InKey, std::tuple<Out<OutKey, Value>>, Reduce<InKey, Value, Reducer, OutKey>, Value> {
111 public:
112 using baseT = TT<InKey, std::tuple<Out<OutKey, Value>>, Reduce<InKey, Value, Reducer, OutKey>, Value>;
113
114 Reduce(Edge<InKey, Value> &in, Edge<OutKey, Value> &out, OutKey dest_key = OutKey(), std::size_t nitems = 1,
115 World &world = default_execution_context())
116 : baseT(edges(in), edges(out, Edge<OutKey, Value>("reduce")), "Reduce", {"in"}, {"out"}, world)
117 , dest_key_(dest_key)
118 , nitems_(nitems) {}
119
120 void op(const InKey &key, baseT::input_values_tuple_type &&indata, std::tuple<Out<OutKey, Value>> &outdata) {
121 std::lock_guard<std::mutex> lock(mutex_);
122 if (nitems_) {
123 reducer_(value_, baseT::get<0>(indata));
124 --nitems_;
125 }
126 if (nitems_ == 0) {
127 binary_tree_reduce_.set_arg<0>(world.rank(), std::move(value_));
128 }
129 }
130
131 private:
132 OutKey dest_key_;
133 size_t nitems_;
134 std::mutex mutex_;
135 Value value_;
136 Reducer reducer_;
137}; // class Reduce
138#endif
139
140} // namespace ttg
141
142#endif // TTG_REDUCE_H
a binary spanning tree of integers in the [0,size) interval
Definition tree.h:18
int parent_key(const int child_key) const
Definition tree.h:33
const auto size() const
Definition tree.h:27
std::pair< int, int > child_keys(const int parent_key) const
Definition tree.h:41
generic binary reduction of a set of key-value pairs.
Definition reduce.h:32
typename BinaryTreeReduce::ttT baseT
Definition reduce.h:34
BinaryTreeReduce(Edge< int, Value > &in, Edge< OutKey, Value > &out, int root=0, OutKey dest_key=OutKey(), BinaryOp op=BinaryOp{}, World world=ttg::default_execution_context(), int max_key=-1, Edge< int, Value > inout=Edge< int, Value >{}, Edge< int, Value > inout_l=Edge< int, Value >{}, Edge< int, Value > inout_r=Edge< int, Value >{})
Definition reduce.h:36
void op(const int &key, typename baseT::input_values_tuple_type &&indata, std::tuple< Out< int, Value >, Out< int, Value >, Out< int, Value >, Out< OutKey, Value > > &outdata)
Definition reduce.h:48
Edge is used to connect In and Out terminals.
Definition edge.h:26
int rank() const
Definition world.h:205
top-level TTG namespace contains runtime-neutral functionality
Definition keymap.h:9
auto fuse(const Edge< keyT, valuesT > &...args)
Fuse edges into one This allows receiving one data from either of the combined edges.
Definition func.h:138
World default_execution_context()
Accesses the default backend's default execution context.
Definition run.h:110
int rank(World world=default_execution_context())
Definition run.h:127
auto edges(inedgesT &&...args)
Make a tuple of Edges to pass to.
Definition func.h:148