diff --git a/src/graph_optimizations.jl b/src/graph_optimizations.jl index 1ebd793..2ba5942 100644 --- a/src/graph_optimizations.jl +++ b/src/graph_optimizations.jl @@ -1,41 +1,96 @@ function node_fusion(graph::DAG, n1::ComputeTaskNode, n2::DataTaskNode, n3::ComputeTaskNode) if !(n1 in graph) || !(n2 in graph) || !(n3 in graph) - error("[Node Fusion] Given nodes are not part of the given graph") + error("[Node Fusion] The given nodes are not part of the given graph") end - required_edge1 = Edge(Tuple{ComputeTaskNode, DataTaskNode}(Ref(n1), Ref(n2))) - required_edge2 = Edge(Tuple{DataTaskNode, ComputeTaskNode}(Ref(n2), Ref(n3))) + required_edge1 = make_edge(n1, n2) + required_edge2 = make_edge(n2, n3) if !(required_edge1 in graph) || !(required_edge2 in graph) - error("[Node Fusion] Given nodes are not connected by edges which is required for node fusion") + error("[Node Fusion] The given nodes are not connected by edges which is required for node fusion") end - # TODO: Perform node fusion + # save children and parents + n1_children = children(graph, n1) + n3_parents = parents(graph, n3) + + # remove the edges and nodes that will be replaced by the fused node + remove_edge(graph, required_edge1) + remove_edge(graph, required_edge2) + remove_node(graph, n1) + remove_node(graph, n2) + remove_node(graph, n3) + + # create new node with the fused compute task + new_node = ComputeTaskNode(FusedComputeTask{typeof(n1), typeof(n3)}()) + insert_node(graph, new_node) + + for child in n1_children + insert_edge(graph, make_edge(child, new_node)) + end + + for parent in n3_parents + insert_edge(graph, make_edge(new_node, parent)) + end + + return nothing end function node_reduction(graph::DAG, n1::Node, n2::Node) if !(n1 in graph) || !(n2 in graph) - error("[Node Reduction] Given nodes are not part of the given graph") + error("[Node Reduction] The given nodes are not part of the given graph") end - prerequisite_nodes = children(graph, n1) - if prerequisite_nodes != children(graph, n2) - error("[Node Reduction] Given nodes do not have equal prerequisite nodes which is required for node reduction") + if typeof(n1) != typeof(n2) + error("[Node Reduction] The given nodes are not of the same type") end - # TODO: Perform node reduction + # save n2 parents and children + n2_children = children(graph, n2) + n2_parents = parents(graph, n2) + + if n2_children != children(graph, n1) + error("[Node Reduction] The given nodes do not have equal prerequisite nodes which is required for node reduction") + end + + # remove n2 and all its parents and children + for child in n2_children + remove_edge(graph, make_edge(child, n2)) + end + for parent in n2_parents + remove_edge(graph, make_edge(n2, parent)) + + # add parents of n2 to n1 + insert_edge(graph, make_edge(n1, parent)) + end + remove_node(graph, n2) + + return nothing end function node_split(graph::DAG, n1::Node) if !(n1 in graph) - error("[Node Split] Given node is not part of the given graph") + error("[Node Split] The given node is not part of the given graph") end - subsequent_nodes = parents(graph, n1) - if size(subsequent_nodes) <= 1 - error("[Node Split] Given node does not have multiple parents which is required for node split") + n1_parents = parents(graph, n1) + n1_children = children(graph, n1) + + if size(n1_parents) <= 1 + error("[Node Split] The given node does not have multiple parents which is required for node split") end - # TODO: Perform node split + for parent in n1_parents + n_copy = copy(n1) + insert_node(graph, n_copy) + insert_edge(graph, make_edge(n_copy, parent)) + remove_edge(graph, make_edge(n1, parent)) + + for child in n1_children + insert_edge(graph, make_edge(child, n_copy)) + end + end + + return nothing end diff --git a/src/node_functions.jl b/src/node_functions.jl index e69de29..d56914a 100644 --- a/src/node_functions.jl +++ b/src/node_functions.jl @@ -0,0 +1,12 @@ + +function make_edge(n1::Node, n2::Node) + error("Can only create edges from compute to data node or reverse") +end + +function make_edge(n1::ComputeTaskNode, n2::DataTaskNode) + return Edge(Tuple{ComputeTaskNode, DataTaskNode}(Ref(n1), Ref(n2))) +end + +function make_edge(n1::DataTaskNode, n2::ComputeTaskNode) + return Edge(Tuple{DataTaskNode, ComputeTaskNode}(Ref(n2), Ref(n3))) +end diff --git a/src/task_functions.jl b/src/task_functions.jl index 9376e9b..78f5279 100644 --- a/src/task_functions.jl +++ b/src/task_functions.jl @@ -24,6 +24,10 @@ compute_effort(t::ComputeTaskS2) = 10 compute_effort(t::ComputeTaskU) = 6 compute_effort(t::ComputeTaskV) = 20 compute_effort(t::ComputeTaskP) = 15 +function compute_effort(t::FusedComputeTask) + (T1, T2) = collect(typeof(t).parameters) + return compute_effort(T1()) + compute_effort(T2()) +end # actual compute functions for the tasks can stay undefined for now # compute(t::ComputeTaskU, data::Any) = mycomputation(data) diff --git a/src/tasks.jl b/src/tasks.jl index c137497..cfe9a2d 100644 --- a/src/tasks.jl +++ b/src/tasks.jl @@ -26,3 +26,6 @@ end # u task with 1 child struct ComputeTaskU <: AbstractComputeTask end + +struct FusedComputeTask{T1<:AbstractComputeTask, T2<:AbstractComputeTask} <: AbstractComputeTask +end