# functions for "cleaning" nodes, i.e. regenerating the possible operations for a node # function to find node fusions involving the given node if it's a data node # pushes the found fusion everywhere it needs to be and returns nothing function find_fusions!(graph::DAG, node::DataTaskNode) # if there is already a fusion here, skip if !ismissing(node.nodeFusion) return nothing end if length(node.parents) != 1 || length(node.children) != 1 return nothing end child_node = first(node.children) parent_node = first(node.parents) if !(child_node in graph) || !(parent_node in graph) error("Parents/Children that are not in the graph!!!") end if length(child_node.parents) != 1 return nothing end nf = NodeFusion((child_node, node, parent_node)) push!(graph.possibleOperations.nodeFusions, nf) push!(child_node.nodeFusions, nf) node.nodeFusion = nf push!(parent_node.nodeFusions, nf) return nothing end function find_fusions!(graph::DAG, node::ComputeTaskNode) # just find fusions in neighbouring DataTaskNodes for child in node.children find_fusions!(graph, child) end for parent in node.parents find_fusions!(graph, parent) end return nothing end function find_reductions!(graph::DAG, node::Node) # there can only be one reduction per node, avoid adding duplicates if !ismissing(node.nodeReduction) return nothing end reductionVector = nothing # possible reductions are with nodes that are partners, i.e. parents of children partners_ = partners(node) delete!(partners_, node) for partner in partners_ if partner ∉ graph.nodes error("Partner is not part of the graph") end if can_reduce(node, partner) if Set(node.children) != Set(partner.children) error("Not equal children") end if reductionVector === nothing # only when there's at least one reduction partner, insert the vector reductionVector = Vector{Node}() push!(reductionVector, node) end push!(reductionVector, partner) end end if reductionVector !== nothing nr = NodeReduction(reductionVector) push!(graph.possibleOperations.nodeReductions, nr) for node in reductionVector if !ismissing(node.nodeReduction) # it can happen that the dirty node becomes part of an existing NodeReduction and overrides those ones now # this is only a problem insofar the existing NodeReduction has to be deleted and replaced also in the possibleOperations invalidate_caches!(graph, node.nodeReduction) end node.nodeReduction = nr end end return nothing end function find_splits!(graph::DAG, node::Node) if !ismissing(node.nodeSplit) return nothing end if (can_split(node)) ns = NodeSplit(node) push!(graph.possibleOperations.nodeSplits, ns) node.nodeSplit = ns end return nothing end # "clean" the operations on a dirty node function clean_node!(graph::DAG, node::Node) sort_node!(node) find_fusions!(graph, node) find_reductions!(graph, node) return find_splits!(graph, node) end