Commit df021243 by FritzFlorian

Working recursive invocations.

Recursion works by using a function node, calling the graph again. We separated an graph invocation form an function invocation within an graph, making the graph only handle one concern.
parent b48c46fc
......@@ -4,6 +4,7 @@
#include <tuple>
#include <array>
#include <pls/pls.h>
#include <pls/dataflow/internal/inputs.h>
#include <pls/dataflow/internal/outputs.h>
#include <pls/dataflow/internal/function_node.h>
......@@ -17,31 +18,53 @@ int main() {
// Define
graph<inputs<int, int>, outputs<int>> graph;
auto func1 = [](const int &i1, const int &i2, int &o1) {
std::cout << "Add up " << i1 << " and " << i2 << "..." << std::endl;
o1 = i1 + i2;
auto triple = [](const int &i1, int &o1) {
o1 = i1 * 3;
};
function_node<inputs<int, int>, outputs<int>, decltype(func1)> node1{func1};
function_node<inputs<int>, outputs<int>, decltype(triple)> triple_node{triple};
auto func2 = [](const int &i1, int &o1) {
std::cout << "Print Result " << i1 << std::endl;
o1 = i1;
auto minus_one = [](const int &i1, int &o1) {
o1 = i1 - 1;
};
function_node<inputs<int>, outputs<int>, decltype(func2)> node2{func2};
function_node<inputs<int>, outputs<int>, decltype(minus_one)> minus_one_node{minus_one};
auto recursion = [&](const int &i1, const int &i2, int &o1) {
if (i1 > 0) {
std::tuple<int> out;
graph.run({i1, i2}, out);
pls::scheduler::wait_for_all();
o1 = std::get<0>(out);
} else {
o1 = i2;
}
};
function_node<inputs<int, int>, outputs<int>, decltype(recursion)> recursion_node{recursion};
// Connect
graph.input<0>() >> node1.in_port<0>();
graph.input<1>() >> node1.in_port<1>();
graph.input<0>() >> minus_one_node.in_port<0>();
minus_one_node.out_port<0>() >> recursion_node.in_port<0>();
node1.out_port<0>() >> node2.in_port<0>();
graph.input<1>() >> triple_node.in_port<0>();
triple_node.out_port<0>() >> recursion_node.in_port<1>();
node2.out_port<0>() >> graph.output<0>();
recursion_node.out_port<0>() >> graph.output<0>();
// Build
graph.build();
// Execute
graph.run({1, 2});
graph.run({1, 1});
graph.run({5, 6});
pls::malloc_scheduler_memory my_scheduler_memory{8, 2u << 18u};
pls::scheduler scheduler{&my_scheduler_memory, 8};
scheduler.perform_work([&] {
// Schedule Execution
std::tuple<int> out1, out2, out3;
graph.run({1, 2}, out1);
graph.run({1, 1}, out2);
graph.run({5, 6}, out3);
// Wait for results and print
pls::scheduler::wait_for_all();
std::cout << std::get<0>(out1) << std::endl;
std::cout << std::get<0>(out2) << std::endl;
std::cout << std::get<0>(out3) << std::endl;
});
}
......@@ -49,7 +49,7 @@ add_library(pls STATIC
include/pls/internal/scheduling/scheduler_impl.h
include/pls/internal/scheduling/task.h src/internal/scheduling/task.cpp
include/pls/internal/scheduling/scheduler_memory.h src/internal/scheduling/scheduler_memory.cpp
include/pls/internal/scheduling/lambda_task.h include/pls/internal/helpers/seqence.h)
include/pls/internal/scheduling/lambda_task.h include/pls/internal/helpers/seqence.h include/pls/dataflow/internal/build_state.h)
# Add everything in `./include` to be in the include path of this project
target_include_directories(pls
PUBLIC
......
......@@ -64,7 +64,7 @@ class function_node<pls::dataflow::inputs<I0, I...>, pls::dataflow::outputs<O0,
template<int POS, typename T>
void token_pushed(token<T> token) {
auto current_memory = get_invocation<invocation_memory>(token);
auto current_memory = get_invocation<invocation_memory>(token.invocation());
std::get<POS>(current_memory->input_buffer_) = token;
auto remaining_inputs = --(current_memory->inputs_missing_);
......@@ -141,7 +141,6 @@ class function_node<pls::dataflow::inputs<I0, I...>, pls::dataflow::outputs<O0,
};
private:
// Input/Output ports
multi_in_port_type in_port_;
multi_out_port_type out_port_;
......
......@@ -2,17 +2,22 @@
#ifndef PLS_DATAFLOW_INTERNAL_NODE_H_
#define PLS_DATAFLOW_INTERNAL_NODE_H_
#include "build_state.h"
namespace pls {
namespace dataflow {
namespace internal {
/**
* Represents a single piece included in a dataflow graph.
* This can be anything connected to form the dataflow that requires
* memory during invocation and is present in the connected flow graph.
*/
class node {
template<typename INS, typename OUTS>
friend
class graph;
enum state { fresh, building, built, teardown };
public:
virtual int num_successors() const = 0;
virtual node *successor_at(int pos) const = 0;
......@@ -22,18 +27,15 @@ class node {
virtual bool is_fully_connected() const = 0;
template<typename M, typename T>
M *get_invocation(token<T> token) {
return token.invocation().template get_instance_buffer<M>(memory_index_);
template<typename M>
M *get_invocation(invocation_info invocation) {
return invocation.template get_instance_buffer<M>(memory_index_);
}
// TODO: Remove
void set_memory_index(int i) { memory_index_ = i; }
private:
int memory_index_{0};
node *direct_successor_{nullptr};
state state_{fresh};
build_state build_state_{build_state::fresh};
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment