Skip to content

Commit 81abca6

Browse files
committed
Add test for vector<int> x int reduction
Signed-off-by: Joseph Schuchart <schuchart@icl.utk.edu>
1 parent cfe560e commit 81abca6

4 files changed

Lines changed: 130 additions & 44 deletions

File tree

examples/test/test.cc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
#include "ttg.h"
55

6+
#include "ttg/serialization.h"
7+
#include "ttg/serialization/std/vector.h"
8+
69
/* TODO: Get rid of using statement */
710
using namespace ttg;
811

@@ -301,6 +304,55 @@ class Everything5 {
301304
}
302305
};
303306

307+
308+
class Everything6 {
309+
static void p(std::tuple<Out<keyT, int>> &out) {
310+
ttg::print("produced ", 0);
311+
send<0>(0, 0, out);
312+
}
313+
314+
static void a(const keyT &key, const int &value, std::tuple<Out<void, int>, Out<keyT, int>> &out) {
315+
if (value < 100) {
316+
send<1>(key + 1, value + 1, out);
317+
sendv<0>(value, out);
318+
}
319+
}
320+
321+
static void c(const std::vector<int> &values, std::tuple<> &out) { ttg::print("consumed ", values.size()); }
322+
323+
// !!!! Edges must be constructed before classes that use them
324+
Edge<keyT, int> P2A, A2A;
325+
Edge<void, int> A2C;
326+
327+
decltype(make_tt<void>(p, edges(), edges(P2A))) wp;
328+
decltype(make_tt(a, edges(fuse(P2A, A2A)), edges(A2C, A2A))) wa;
329+
decltype(make_tt(c, edges(A2C), edges())) wc;
330+
331+
public:
332+
Everything6()
333+
: P2A("P2A")
334+
, A2A("A2A")
335+
, A2C("A2C")
336+
, wp(make_tt<void>(p, edges(), edges(P2A), "producer", {}, {"start"}))
337+
, wa(make_tt(a, edges(fuse(P2A, A2A)), edges(A2C, A2A), "A", {"input"}, {"result", "iterate"}))
338+
, wc(make_tt(c, edges(A2C), edges(), "consumer", {"result"}, {})) {
339+
wc->set_input_reducer<0>([](std::vector<int> &a, const int &b) { a.push_back(b); });
340+
if (wc->get_world().rank() == 0) wc->set_argstream_size<0>(100);
341+
}
342+
343+
void print() { print_ttg(wp.get()); }
344+
345+
std::string dot() { return Dot{}(wp.get()); }
346+
347+
void start() {
348+
wp->make_executable();
349+
wa->make_executable();
350+
wc->make_executable();
351+
if (wp->get_world().rank() == 0) wp->invoke();
352+
}
353+
};
354+
355+
304356
class EverythingComposite {
305357
std::unique_ptr<TTBase> P;
306358
std::unique_ptr<TTBase> AC;
@@ -575,6 +627,10 @@ int try_main(int argc, char **argv) {
575627
std::cout << q5.dot() << std::endl;
576628
q5.start();
577629

630+
Everything6 q6;
631+
std::cout << q6.dot() << std::endl;
632+
q6.start();
633+
578634
Fibonacci fi;
579635
std::cout << fi.dot() << std::endl << std::endl;
580636
if (ttg_default_execution_context().size() == 1)

ttg/ttg/make_tt.h

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,25 @@ struct CallableWrapTTUnwrapTuple<funcT, keyT, output_terminalsT, std::tuple<inpu
9494
// case 1 (keyT != void): void op(auto&& key, input_valuesT&&..., std::tuple<output_terminalsT...>&)
9595
// case 2 (keyT == void): void op(input_valuesT&&..., std::tuple<output_terminalsT...>&)
9696
//
97-
template <typename funcT, typename keyT, typename output_terminalsT, typename... input_valuesT>
97+
template <typename funcT, typename keyT, typename output_terminalsT,
98+
typename terminal_input_values_tupleT, typename args_input_values_tupleT>
9899
class CallableWrapTTArgs
99-
: public TT<keyT, output_terminalsT, CallableWrapTTArgs<funcT, keyT, output_terminalsT, input_valuesT...>,
100-
std::tuple<input_valuesT...>,
101-
typename ttg::meta::drop_last_n<
102-
typename ttg::meta::drop_first_n<boost::callable_traits::args_t<funcT>,
103-
ttg::meta::is_void_v<keyT> ? 0 : 1>::type,
104-
1>::type> {
105-
using baseT = TT<keyT, output_terminalsT, CallableWrapTTArgs<funcT, keyT, output_terminalsT, input_valuesT...>,
106-
std::tuple<input_valuesT...>,
107-
typename ttg::meta::drop_last_n<
108-
typename ttg::meta::drop_first_n<boost::callable_traits::args_t<funcT>,
109-
ttg::meta::is_void_v<keyT> ? 0 : 1>::type,
110-
1>::type>;
100+
: public TT<keyT, output_terminalsT,
101+
CallableWrapTTArgs<funcT, keyT, output_terminalsT,
102+
terminal_input_values_tupleT,
103+
args_input_values_tupleT>,
104+
terminal_input_values_tupleT,
105+
args_input_values_tupleT>
106+
{
107+
using baseT = TT<keyT, output_terminalsT,
108+
CallableWrapTTArgs<funcT, keyT, output_terminalsT,
109+
terminal_input_values_tupleT,
110+
args_input_values_tupleT>,
111+
terminal_input_values_tupleT,
112+
args_input_values_tupleT>;
111113

112114
using input_values_tuple_type = typename baseT::input_values_tuple_type;
113-
using input_refs_tuple_type = typename baseT::input_refs_tuple_type;
115+
using args_refs_tuple_type = typename baseT::args_refs_tuple_type;
114116
using input_edges_type = typename baseT::input_edges_type;
115117
using output_edges_type = typename baseT::output_edges_type;
116118

@@ -152,41 +154,40 @@ class CallableWrapTTArgs
152154
: baseT(name, innames, outnames), func(std::forward<funcT_>(f)) {}
153155

154156
template <typename Key, typename ArgsTuple>
155-
std::enable_if_t<std::is_same_v<ArgsTuple, input_refs_tuple_type> &&
156-
!ttg::meta::is_empty_tuple_v<input_refs_tuple_type> && !ttg::meta::is_void_v<Key>,
157+
std::enable_if_t<std::is_same_v<ArgsTuple, args_refs_tuple_type> &&
158+
!ttg::meta::is_empty_tuple_v<args_refs_tuple_type> && !ttg::meta::is_void_v<Key>,
157159
void>
158160
op(Key &&key, ArgsTuple &&args_tuple, output_terminalsT &out) {
159161
call_func(std::forward<Key>(key), std::forward<ArgsTuple>(args_tuple), out,
160162
std::make_index_sequence<std::tuple_size<ArgsTuple>::value>{});
161163
};
162164

163165
template <typename ArgsTuple, typename Key = keyT>
164-
std::enable_if_t<std::is_same_v<ArgsTuple, input_refs_tuple_type> &&
165-
!ttg::meta::is_empty_tuple_v<input_refs_tuple_type> && ttg::meta::is_void_v<Key>,
166+
std::enable_if_t<std::is_same_v<ArgsTuple, args_refs_tuple_type> &&
167+
!ttg::meta::is_empty_tuple_v<args_refs_tuple_type> && ttg::meta::is_void_v<Key>,
166168
void>
167169
op(ArgsTuple &&args_tuple, output_terminalsT &out) {
168170
call_func(std::forward<ArgsTuple>(args_tuple), out, std::make_index_sequence<std::tuple_size<ArgsTuple>::value>{});
169171
};
170172

171-
template <typename Key, typename ArgsTuple = input_refs_tuple_type>
173+
template <typename Key, typename ArgsTuple = args_refs_tuple_type>
172174
std::enable_if_t<ttg::meta::is_empty_tuple_v<ArgsTuple> && !ttg::meta::is_void_v<Key>, void>
173175
op(Key &&key, output_terminalsT &out) {
174176
call_func(std::forward<Key>(key), out);
175177
};
176178

177-
template <typename Key = keyT, typename ArgsTuple = input_refs_tuple_type>
179+
template <typename Key = keyT, typename ArgsTuple = args_refs_tuple_type>
178180
std::enable_if_t<ttg::meta::is_empty_tuple_v<ArgsTuple> && ttg::meta::is_void_v<Key>, void>
179181
op(output_terminalsT &out) {
180182
call_func(out);
181183
};
182184
};
183185

184-
template <typename funcT, typename keyT, typename output_terminalsT, typename input_values_tupleT>
185-
struct CallableWrapTTArgsUnwrapTuple;
186-
187-
template <typename funcT, typename keyT, typename output_terminalsT, typename... input_valuesT>
188-
struct CallableWrapTTArgsUnwrapTuple<funcT, keyT, output_terminalsT, std::tuple<input_valuesT...>> {
189-
using type = CallableWrapTTArgs<funcT, keyT, output_terminalsT, std::remove_reference_t<input_valuesT>...>;
186+
template <typename funcT, typename keyT, typename output_terminalsT,
187+
typename terminal_input_values_tupleT, typename args_input_values_tupleT>
188+
struct CallableWrapTTArgsUnwrapTuple {
189+
using type = CallableWrapTTArgs<funcT, keyT, output_terminalsT,
190+
terminal_input_values_tupleT, args_input_values_tupleT>;
190191
};
191192

192193
// Factory function to assist in wrapping a callable with signature
@@ -272,19 +273,20 @@ auto make_tt(funcT &&func, const std::tuple<ttg::Edge<keyT, input_edge_valuesT>.
272273
typename ttg::meta::drop_first_n<func_args_t, std::size_t(void_key ? 0 : 1)>::type,
273274
std::tuple_size_v<func_args_t> - (void_key ? 1 : 2)>::type;
274275
using decayed_input_args_t = ttg::meta::decayed_tuple_t<input_args_t>;
276+
using noref_input_args_t = ttg::meta::nonref_tuple_t<input_args_t>;
275277
// 3. full_input_args_t = !have_void_datum ? input_args_t : input_args_t+void
276278
using full_input_args_t =
277-
std::conditional_t<!have_void_datum, input_args_t, ttg::meta::tuple_concat_t<input_args_t, std::tuple<void>>>;
278-
using wrapT = typename CallableWrapTTArgsUnwrapTuple<funcT, keyT, output_terminals_type, full_input_args_t>::type;
279+
std::conditional_t<!have_void_datum, noref_input_args_t, ttg::meta::tuple_concat_t<noref_input_args_t, std::tuple<void>>>;
280+
using wrapT = typename CallableWrapTTArgsUnwrapTuple<funcT, keyT, output_terminals_type, input_values_tuple_type, full_input_args_t>::type;
279281
// not sure if we need this level of type checking ...
280282
// TODO determine the generic signature of func
281283
if constexpr (!void_key) {
282284
static_assert(
283285
std::is_same_v<typename std::tuple_element<0, func_args_t>::type, const keyT &>,
284286
"ttg::make_tt(func, inedges, outedges): first argument of func must be const keyT& (unless keyT = void)");
285287
}
286-
static_assert(std::is_same_v<decayed_input_args_t, input_values_tuple_type>,
287-
"ttg::make_tt(func, inedges, outedges): inedges value types do not match argument types of func");
288+
//static_assert(std::is_same_v<decayed_input_args_t, input_values_tuple_type>,
289+
// "ttg::make_tt(func, inedges, outedges): inedges value types do not match argument types of func");
288290
static_assert(
289291
std::is_same_v<typename std::tuple_element<num_args - 1, func_args_t>::type, output_terminals_type &>,
290292
"ttg::make_tt(func, inedges, outedges): last argument of func must be std::tuple<output_terminals_type>&");

ttg/ttg/parsec/ttg.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,7 @@ namespace ttg_parsec {
818818
using input_refs_tuple_type =
819819
std::conditional_t<ttg::meta::is_none_void_v<input_edge_typesT>, input_refs_full_tuple_type,
820820
typename ttg::meta::drop_last_n<input_refs_full_tuple_type, std::size_t{1}>::type>;
821+
using input_crefs_tuple_type = ttg::meta::add_const_tuple_t<input_refs_tuple_type>;
821822
using args_refs_tuple_type =
822823
std::conditional_t<ttg::meta::is_none_void_v<input_edge_typesT>, args_refs_full_tuple_type,
823824
typename ttg::meta::drop_last_n<args_refs_full_tuple_type, std::size_t{1}>::type>;
@@ -1417,7 +1418,7 @@ namespace ttg_parsec {
14171418
}
14181419
task->parsec_task.data[i].data_in = copy;
14191420
} else {
1420-
reducer(*reinterpret_cast<std::decay_t<valueT>*>(copy->device_private), value);
1421+
reducer(*reinterpret_cast<std::decay_t<input_arg_type>*>(copy->device_private), value);
14211422
}
14221423
} else {
14231424
reducer(); // even if this was a control input, must execute the reducer for possible side effects
@@ -1956,15 +1957,15 @@ namespace ttg_parsec {
19561957
// Used by invoke to set all arguments associated with a task
19571958
template <typename Key, size_t... IS>
19581959
std::enable_if_t<ttg::meta::is_none_void_v<Key>, void> set_args(std::index_sequence<IS...>, const Key &key,
1959-
const input_refs_tuple_type &args) {
1960+
const input_crefs_tuple_type &args) {
19601961
int junk[] = {0, (set_arg<IS>(key, TT::get<IS>(args)), 0)...};
19611962
junk[0]++;
19621963
}
19631964

19641965
// Used by invoke to set all arguments associated with a task
19651966
template <typename Key = keyT, size_t... IS>
19661967
std::enable_if_t<ttg::meta::is_void_v<Key>, void> set_args(std::index_sequence<IS...>,
1967-
const input_refs_tuple_type &args) {
1968+
const input_crefs_tuple_type &args) {
19681969
int junk[] = {0, (set_arg<IS>(TT::get<IS>(args)), 0)...};
19691970
junk[0]++;
19701971
}
@@ -2592,39 +2593,39 @@ namespace ttg_parsec {
25922593
// Manual injection of a task with all input arguments specified as a tuple
25932594
template <typename Key = keyT>
25942595
std::enable_if_t<!ttg::meta::is_void_v<Key> &&
2595-
!ttg::meta::is_empty_tuple_v<input_refs_tuple_type>, void>
2596-
invoke(const Key &key, const input_refs_tuple_type &args) {
2596+
!ttg::meta::is_empty_tuple_v<input_crefs_tuple_type>, void>
2597+
invoke(const Key &key, const input_crefs_tuple_type &args) {
25972598
TTG_OP_ASSERT_EXECUTABLE();
2598-
set_args(std::make_index_sequence<std::tuple_size<input_refs_tuple_type>::value>{}, key, args);
2599+
set_args(std::make_index_sequence<std::tuple_size<input_crefs_tuple_type>::value>{}, key, args);
25992600
}
26002601

26012602
// Manual injection of a key-free task and all input arguments specified as a tuple
26022603
template <typename Key = keyT>
2603-
std::enable_if_t<ttg::meta::is_void_v<Key> && !ttg::meta::is_empty_tuple_v<input_refs_tuple_type>, void>
2604-
invoke(const input_refs_tuple_type &args) {
2604+
std::enable_if_t<ttg::meta::is_void_v<Key> && !ttg::meta::is_empty_tuple_v<input_crefs_tuple_type>, void>
2605+
invoke(const input_crefs_tuple_type &args) {
26052606
TTG_OP_ASSERT_EXECUTABLE();
2606-
set_args(std::make_index_sequence<std::tuple_size<input_refs_tuple_type>::value>{}, args);
2607+
set_args(std::make_index_sequence<std::tuple_size<input_crefs_tuple_type>::value>{}, args);
26072608
}
26082609

26092610
// Manual injection of a task that has no arguments
26102611
template <typename Key = keyT>
2611-
std::enable_if_t<!ttg::meta::is_void_v<Key> && ttg::meta::is_empty_tuple_v<input_refs_tuple_type>, void>
2612+
std::enable_if_t<!ttg::meta::is_void_v<Key> && ttg::meta::is_empty_tuple_v<input_crefs_tuple_type>, void>
26122613
invoke(const Key &key) {
26132614
TTG_OP_ASSERT_EXECUTABLE();
26142615
set_arg<keyT>(key);
26152616
}
26162617

26172618
// Manual injection of a task that has no key or arguments
26182619
template <typename Key = keyT>
2619-
std::enable_if_t<ttg::meta::is_void_v<Key> && ttg::meta::is_empty_tuple_v<input_refs_tuple_type>, void>
2620+
std::enable_if_t<ttg::meta::is_void_v<Key> && ttg::meta::is_empty_tuple_v<input_crefs_tuple_type>, void>
26202621
invoke() {
26212622
TTG_OP_ASSERT_EXECUTABLE();
26222623
set_arg<keyT>();
26232624
}
26242625

26252626
// overrides TTBase::invoke()
26262627
void invoke() override {
2627-
if constexpr (ttg::meta::is_void_v<keyT> && ttg::meta::is_empty_tuple_v<input_refs_tuple_type>)
2628+
if constexpr (ttg::meta::is_void_v<keyT> && ttg::meta::is_empty_tuple_v<input_crefs_tuple_type>)
26282629
invoke<keyT>();
26292630
else
26302631
TTBase::invoke();

ttg/ttg/util/meta.h

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ namespace ttg {
6767
};
6868

6969
// tuple<Ts...> -> tuple<std::remove_reference_t<Ts>...>
70-
template <typename T, typename Enabler = void>
70+
template <typename T>
7171
struct nonref_tuple;
7272

7373
template <typename... Ts>
@@ -79,7 +79,7 @@ namespace ttg {
7979
using nonref_tuple_t = typename nonref_tuple<Tuple>::type;
8080

8181
// tuple<Ts...> -> tuple<std::decay_t<Ts>...>
82-
template <typename T, typename Enabler = void>
82+
template <typename T>
8383
struct decayed_tuple;
8484

8585
template <typename... Ts>
@@ -90,6 +90,33 @@ namespace ttg {
9090
template <typename Tuple>
9191
using decayed_tuple_t = typename decayed_tuple<Tuple>::type;
9292

93+
94+
// like std::add_const but adds const to references
95+
template<typename T>
96+
struct add_const {
97+
using type = std::add_const_t<T>;
98+
};
99+
100+
template<typename T>
101+
struct add_const<T&> {
102+
using type = std::add_lvalue_reference_t<std::add_const_t<T>>;
103+
};
104+
105+
template<typename T>
106+
using add_const_t = typename add_const<T>::type;
107+
108+
// tuple<Ts...> -> tuple<std::add_const<Ts>...>
109+
template <typename T>
110+
struct add_const_tuple;
111+
112+
template <typename... Ts>
113+
struct add_const_tuple<std::tuple<Ts...>> {
114+
using type = std::tuple<typename add_const<Ts>::type...>;
115+
};
116+
117+
template <typename Tuple>
118+
using add_const_tuple_t = typename add_const_tuple<Tuple>::type;
119+
93120
template <typename Tuple1, typename Tuple2>
94121
struct tuple_concat;
95122

0 commit comments

Comments
 (0)