Work on optimization functions

This commit is contained in:
2023-05-30 19:10:44 +02:00
parent 190a4252f8
commit 5bf660618d
6 changed files with 113 additions and 71 deletions

View File

@ -49,12 +49,12 @@ is_exit_node(graph::DAG, node::Node) = size(parents(graph, node)) == 0
function insert_node(graph::DAG, node::Node)
push!(graph.nodes, node)
return nothing
return node
end
function insert_edge(graph::DAG, edge::Edge)
push!(graph.edges, edge)
return nothing
return edge
end
function remove_node(graph::DAG, node::Node)
@ -91,6 +91,15 @@ function compute_intensity(graph::DAG)
return compute_effort(graph) / data_sum
end
function get_exit_node(graph::DAG)
for node in graph.nodes
if (is_exit_node(graph, node))
return node
end
end
error("The given graph has no exit node! It is either empty or not acyclic!")
end
function show_nodes(io, graph::DAG)
print(io, "[")
first = true
@ -98,7 +107,7 @@ function show_nodes(io, graph::DAG)
if first
first = false
else
print(", ")
print(io, ", ")
end
print(io, n)
end
@ -112,7 +121,7 @@ function show_edges(io, graph::DAG)
if first
first = false
else
print(", ")
print(io, ", ")
end
print(io, e)
end
@ -121,13 +130,13 @@ end
function show(io::IO, graph::DAG)
println(io, "Graph:")
print(" Nodes: ")
print(io, " Nodes: ")
show_nodes(io, graph)
println()
print(" Edges: ")
println(io)
print(io, " Edges: ")
show_edges(io, graph)
println()
println(" Total Compute Effort: ", compute_effort(graph))
println(" Total Data Transfer: ", data(graph))
println(" Total Compute Intensity: ", compute_intensity(graph))
println(io)
println(io, " Total Compute Effort: ", compute_effort(graph))
println(io, " Total Data Transfer: ", data(graph))
println(io, " Total Compute Intensity: ", compute_intensity(graph))
end

View File

@ -13,24 +13,42 @@ function node_fusion(graph::DAG, n1::ComputeTaskNode, n2::DataTaskNode, n3::Comp
# save children and parents
n1_children = children(graph, n1)
n2_parents = parents(graph, n2)
n3_parents = parents(graph, n3)
if length(n2_parents) > 1
error("[Node Fusion] The given data node has more than one parent")
end
# 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)
# get n3's children now so it automatically excludes n2
n3_children = children(graph, n3)
remove_node(graph, n3)
# create new node with the fused compute task
new_node = ComputeTaskNode(FusedComputeTask{typeof(n1.task), typeof(n3.task)}())
insert_node(graph, new_node)
# "repoint" children of n1 to the new node
for child in n1_children
remove_edge(graph, make_edge(child, n1))
insert_edge(graph, make_edge(child, new_node))
end
# "repoint" children of n3 to the new node
for child in n3_children
remove_edge(graph, make_edge(child, n3))
insert_edge(graph, make_edge(child, new_node))
end
# "repoint" parents of n3 from new node
for parent in n3_parents
remove_edge(graph, make_edge(n3, parent))
insert_edge(graph, make_edge(new_node, parent))
end
@ -66,7 +84,7 @@ function node_reduction(graph::DAG, n1::Node, n2::Node)
end
remove_node(graph, n2)
return nothing
return n1
end
function node_split(graph::DAG, n1::Node)
@ -77,7 +95,7 @@ function node_split(graph::DAG, n1::Node)
n1_parents = parents(graph, n1)
n1_children = children(graph, n1)
if size(n1_parents) <= 1
if length(n1_parents) <= 1
error("[Node Split] The given node does not have multiple parents which is required for node split")
end
@ -94,3 +112,39 @@ function node_split(graph::DAG, n1::Node)
return nothing
end
# function to generate all possible optmizations on the graph
function generate_options(graph::DAG)
options = (fusions = Vector{Tuple{ComputeTaskNode, DataTaskNode, ComputeTaskNode}}(),
reductions = Vector{Tuple{Node, Node}}(),
splits = Vector{Tuple{Node}}())
# find possible node fusions
for node in graph.nodes
if (typeof(node) <: DataTaskNode)
node_parents = parents(graph, node)
if length(node_parents) != 1
# data node can only have a single parent
continue
end
parent_node = node_parents[1]
node_children = children(graph, node)
if length(node_children) != 1
# this node is an entry node or has multiple children which should not be possible
continue
end
child_node = node_children[1]
push!(options.fusions, (child_node, node, parent_node))
end
end
# find possible node reductions
# find possible node splits
return options
end

View File

@ -13,8 +13,8 @@ include("graph_optimizations.jl")
export Node, Edge, ComputeTaskNode, DataTaskNode, DAG
export AbstractTask, AbstractComputeTask, AbstractDataTask, DataTask, ComputeTaskP, ComputeTaskS1, ComputeTaskS2, ComputeTaskV, ComputeTaskU, FusedComputeTask
export make_node, make_edge, insert_node, insert_edge, is_entry_node, is_exit_node, parents, children, compute, data, compute_effort, compute_intensity
export node_fusion, node_reduction, node_split
export make_node, make_edge, insert_node, insert_edge, is_entry_node, is_exit_node, parents, children, compute, data, compute_effort, compute_intensity, get_exit_node
export node_fusion, node_reduction, node_split, generate_options
export ==, in, show

View File

@ -50,7 +50,7 @@ show(io::IO, t::ComputeTaskU) = print("ComputeU")
show(io::IO, t::ComputeTaskV) = print("ComputeV")
function show(io::IO, t::FusedComputeTask)
(T1, T2) = collect(typeof(t).parameters)
(T1, T2) = get_types(t)
print(io, "ComputeFuse(", T1(), ", ", T2(), ")")
end

View File

@ -29,3 +29,5 @@ end
struct FusedComputeTask{T1<:AbstractComputeTask, T2<:AbstractComputeTask} <: AbstractComputeTask
end
get_types(::FusedComputeTask{T1, T2}) where {T1, T2} = (T1, T2)