Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port Graph Optimizations #52

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open

Port Graph Optimizations #52

wants to merge 12 commits into from

Conversation

tanneberger
Copy link
Member

@tanneberger tanneberger commented Jul 27, 2023

About

This pull requests add functionality, so the port graph can be first optimized before instantiating.

  • Graph Expansion with Path Merging
  • Dead Edge Elimination by looking at triggers and dependencies and taking the shortest path
  • Instantiating

Current Algorithm

Create a spanning tree for every port and then squash the edges together so ideally only a tree of depth 1 remains.

Challanges

Given a port-graph like this:

graph TD;
    A-->B;
    X((R1)) --> A;
    B-->D;
    B-->C;
    C-->Y((R2));
Loading

The current graph optimizer would create something like this:

graph TD;
    X((R1)) --> A;
    A-->B;
    A-->C;
    B-->C;
    B-->D;
    A-->D;
    C-->Y((R2));
Loading

If B just forwards data and

Dead Path Elimination

Paths: (A-->D, A-->B and B-->C) can be eliminated with the following reasoning:

  • We take a look at all the ports that have triggers. Then taking all the downstream ports that have dependencies and then determine the shortest path between them.
graph TD;
    X((R1)) --> A;
    A-->C;
    C-->Y((R2));
Loading
target Cpp;

reactor A {
    output out: void;
    timer t(500ms);

    reaction (t) -> out {=
        out.set();
    =}
}

reactor C {
    input in: void;

    reaction(in) {=
        std::cout << "C triggert" << std::endl;
    =}
}

reactor D {
    input in: void;

    reaction(in) {=
        std::cout << "D triggert" << std::endl;
    =}
}

reactor B {
    input in: void;

    c = new C();
    d = new D();
    
    in -> c.in;
    in -> d.in;

}


main reactor Forward {
    a = new A();
    b = new B();

    a.out -> b.in;
}

@tanneberger tanneberger added the enhancement Enhancement of existing feature label Jul 27, 2023
@tanneberger tanneberger self-assigned this Jul 27, 2023
@tanneberger tanneberger requested a review from cmnrd July 27, 2023 11:48
@tanneberger tanneberger changed the title Port Graph Optimizations [[DRAFT]] Port Graph Optimizations Jul 27, 2023
@tanneberger tanneberger force-pushed the optimizations branch 3 times, most recently from 4032199 to 64e3612 Compare August 21, 2023 13:53
@tanneberger tanneberger force-pushed the optimizations branch 8 times, most recently from 50958e6 to ddbd80e Compare August 25, 2023 06:30
@tanneberger tanneberger changed the title [[DRAFT]] Port Graph Optimizations Port Graph Optimizations Aug 31, 2023
Copy link
Contributor

@cmnrd cmnrd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

// Physical + x
{std::make_pair<ConnectionType, ConnectionType>(Physical, Normal), Physical},
{std::make_pair<ConnectionType, ConnectionType>(Physical, Delayed), Invalid}, // !!!
{std::make_pair<ConnectionType, ConnectionType>(Physical, Enclaved), PhysicalEnclaved},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all these cases should be invalid for now (except for Phycical + Normal)

// PhysicalEnclaved + x
{std::make_pair<ConnectionType, ConnectionType>(PhysicalEnclaved, Normal), PhysicalEnclaved},
{std::make_pair<ConnectionType, ConnectionType>(PhysicalEnclaved, Delayed), Invalid}, // !!!
{std::make_pair<ConnectionType, ConnectionType>(PhysicalEnclaved, Enclaved), PhysicalEnclaved},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all these cases should be invalid for now (except for PhycicalEnclaved + Normal)

@@ -37,7 +37,7 @@ public:
virtual ~ReactorElement() = default;

// not copyable, but movable
ReactorElement(const ReactorElement&) = delete;
ReactorElement(const ReactorElement&) = default;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copy constructor is deleted on purpose and we should try to avoid enabling it

@@ -48,6 +48,13 @@ set_target_properties(${LIB_TARGET} PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1)

option(GRAPH_OPTIMIZATIONS "Graph optimizations" ON)
if(GRAPH_OPTIMIZATIONS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be handled more conveniently in config.hh.in

@@ -63,8 +63,20 @@ void Environment::register_input_action(BaseAction* action) {
}

void Environment::optimize() {
// no optimizations
optimized_graph_ = graph_;
#if GRAPH_OPTIMIZATIONS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easier:

  constexpr bool enable_optimizations = (GRAPH_OPTIMIZATIONS == 1);

@@ -39,10 +39,10 @@ ReactorElement::ReactorElement(const std::string& name, ReactorElement::Type typ
container->register_action(reinterpret_cast<BaseAction*>(this)); // NOLINT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
container->register_action(reinterpret_cast<BaseAction*>(this)); // NOLINT
container->register_action(static_cast<BaseAction*>(this)); // NOLINT

break;
case Type::Output:
container->register_output(reinterpret_cast<BasePort*>(this)); // NOLINT
container->register_output(static_cast<BasePort*>(this)); // NOLINT
break;
case Type::Reaction:
container->register_reaction(reinterpret_cast<Reaction*>(this)); // NOLINT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
container->register_reaction(reinterpret_cast<Reaction*>(this)); // NOLINT
container->register_reaction(static_cast<Reaction*>(this)); // NOLINT

std::copy_if(keys.begin(), keys.end(), std::back_inserter(has_upstreams),
[](auto element) { return element->connected_to_upstream_actions(); });

// generating all the possible destinations for all sources
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be really helpful to have a more lengthy comment explaining the high level idea of the algorithm.


for (auto edge : path) {
auto property = std::get<1>(edge);
// auto source_port = std::get<0>(edge);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

@tanneberger
Copy link
Member Author

TODO: Mermaid Function fixen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhancement of existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants