WIP regenerate possible operations

This commit is contained in:
Anton Reinhard 2023-06-29 13:57:45 +02:00
parent d24d354fa0
commit 0cd83fedd9
11 changed files with 115 additions and 73 deletions

View File

@ -14,10 +14,13 @@ include("graph_operations.jl")
include("import.jl")
include("utility.jl")
include("abc_model/tasks.jl")
include("abc_model/task_functions.jl")
export Node, Edge, ComputeTaskNode, DataTaskNode, DAG
export AbstractTask, AbstractComputeTask, AbstractDataTask, DataTask, ComputeTaskP, ComputeTaskS1, ComputeTaskS2, ComputeTaskV, ComputeTaskU, ComputeTaskSum, FusedComputeTask
export make_node, make_edge, insert_node, insert_edge, is_entry_node, is_exit_node, parents, children, compute, graph_properties, get_exit_node, is_valid
export NodeFusion, NodeReduction, NodeSplit, push_operation!, pop_operation!, can_pop, reset_graph!, generate_options
export NodeFusion, NodeReduction, NodeSplit, push_operation!, pop_operation!, can_pop, reset_graph!, get_operations
export import_txt
export ==, in, show

View File

@ -0,0 +1,21 @@
# define compute_efforts tasks computation
# put some "random" numbers here for now
compute_effort(t::ComputeTaskS1) = 10
compute_effort(t::ComputeTaskS2) = 10
compute_effort(t::ComputeTaskU) = 6
compute_effort(t::ComputeTaskV) = 20
compute_effort(t::ComputeTaskP) = 15
compute_effort(t::ComputeTaskSum) = 1
function show(io::IO, t::DataTask)
print(io, "Data", t.data)
end
show(io::IO, t::ComputeTaskS1) = print("ComputeS1")
show(io::IO, t::ComputeTaskS2) = print("ComputeS2")
show(io::IO, t::ComputeTaskP) = print("ComputeP")
show(io::IO, t::ComputeTaskU) = print("ComputeU")
show(io::IO, t::ComputeTaskV) = print("ComputeV")
show(io::IO, t::ComputeTaskSum) = print("ComputeSum")
copy(t::DataTask) = DataTask(t.data)

27
src/abc_model/tasks.jl Normal file
View File

@ -0,0 +1,27 @@
struct DataTask <: AbstractDataTask
data::UInt64
end
# S task with 1 child
struct ComputeTaskS1 <: AbstractComputeTask
end
# S task with 2 children
struct ComputeTaskS2 <: AbstractComputeTask
end
# P task with 0 children
struct ComputeTaskP <: AbstractComputeTask
end
# v task with 2 children
struct ComputeTaskV <: AbstractComputeTask
end
# u task with 1 child
struct ComputeTaskU <: AbstractComputeTask
end
# task that sums all its inputs, n children
struct ComputeTaskSum <: AbstractComputeTask
end

View File

@ -23,7 +23,7 @@ abstract type Operation end
abstract type AppliedOperation end
struct NodeFusion <: Operation
input::Tuple{ComputeTaskNode,DataTaskNode,ComputeTaskNode}
input::Tuple{ComputeTaskNode, DataTaskNode, ComputeTaskNode}
end
struct AppliedNodeFusion <: AppliedOperation
@ -50,17 +50,20 @@ struct AppliedNodeSplit <: AppliedOperation
end
const PossibleOperations = NamedTuple{
(:nodeFusions, :nodeReductions, :nodeSplits),
Tuple{Vector{NodeFusion}, Vector{NodeReduction}, Vector{NodeSplit}}
}
mutable struct PossibleOperations
nodeFusions::Vector{NodeFusion}
nodeReductions::Vector{NodeReduction}
nodeSplits::Vector{NodeSplit}
dirty::Bool
end
function PossibleOperations()
return (
nodeFusions = Vector{NodeFusion}(),
nodeReductions = Vector{NodeReduction}(),
nodeSplits = Vector{NodeSplit}()
)::PossibleOperations
return PossibleOperations(
Vector{NodeFusion}(),
Vector{NodeReduction}(),
Vector{NodeSplit}(),
false
)
end

View File

@ -67,6 +67,7 @@ function insert_node!(graph::DAG, node::Node, track=true)
push!(graph.nodes, node)
if (track) push!(graph.diff.addedNodes, node) end
graph.possibleOperations.dirty = true
return node
end
@ -76,6 +77,7 @@ function insert_edge!(graph::DAG, edge::Edge, track=true)
push!(edge.edge[2].children, edge.edge[1])
if (track) push!(graph.diff.addedEdges, edge) end
graph.possibleOperations.dirty = true
return edge
end
@ -83,6 +85,7 @@ function remove_node!(graph::DAG, node::Node, track=true)
delete!(graph.nodes, node)
if (track) push!(graph.diff.removedNodes, node) end
graph.possibleOperations.dirty = true
return nothing
end
@ -91,6 +94,7 @@ function remove_edge!(graph::DAG, edge::Edge, track=true)
filter!(x -> x != edge.edge[1], edge.edge[2].children)
if (track) push!(graph.diff.removedEdges, edge) end
graph.possibleOperations.dirty = true
return nothing
end

View File

@ -264,7 +264,11 @@ function generate_options(graph::DAG)
end
child_node = pop!(node_children)
push!(options.nodeFusions, NodeFusion((child_node, node, parent_node)))
nf = NodeFusion((child_node, node, parent_node))
push!(options.nodeFusions, nf)
push!(child_node.operations, nf)
push!(node.operations, nf)
push!(parent_node.operations, nf)
end
end
@ -278,29 +282,48 @@ function generate_options(graph::DAG)
push!(visitedNodes, node)
reductionVector = missing
reductionVector = nothing
# possible reductions are with nodes that are partners, i.e. parents of children
for partner in partners(node)
if can_reduce(node, partner)
if reductionVector == missing
if reductionVector === nothing
# only when there's at least one reduction partner, insert the vector
reductionVector = Vector{Node}
push!(reductionVector, node)
push!(options.nodeReductions, NodeReduction(reductionVector))
end
push!(reductionVector, partner)
push!(visitedNodes, partner)
end
end
if reductionVector !== nothing
nr = NodeReduction(reductionVector)
push!(options.nodeReductions, nr)
for node in reductionVector
push!(node.operations, nr)
end
end
end
# find possible node splits
for node in graph.nodes
if (can_split(node))
push!(options.nodeSplits, NodeSplit(node))
ns = NodeSplit(node)
push!(options.nodeSplits, ns)
push!(node.operations, ns)
end
end
return options
options.dirty = false
graph.possibleOperations = options
end
function get_operations(graph::DAG)
if (graph.possibleOperations.dirty)
generate_options(graph)
end
return graph.possibleOperations
end

View File

@ -35,5 +35,5 @@ function ==(e1::Edge, e2::Edge)
end
copy(id::Base.UUID) = Base.UUID(id.value)
copy(n::ComputeTaskNode) = ComputeTaskNode(copy(n.task), copy(n.parents), copy(n.children), copy(n.id))
copy(n::DataTaskNode) = DataTaskNode(copy(n.task), copy(n.parents), copy(n.children), copy(n.id))
copy(n::ComputeTaskNode) = ComputeTaskNode(copy(n.task), copy(n.parents), copy(n.children), copy(n.id), copy(n.operations))
copy(n::DataTaskNode) = DataTaskNode(copy(n.task), copy(n.parents), copy(n.children), copy(n.id), copy(n.operations))

View File

@ -5,6 +5,10 @@ rng = Random.MersenneTwister(0)
abstract type Node end
# declare this type here because it's needed
# the specific operations are declared in graph.jl
abstract type Operation end
struct DataTaskNode <: Node
task::AbstractDataTask
@ -15,6 +19,9 @@ struct DataTaskNode <: Node
# need a unique identifier unique to every *constructed* node
# however, it can be copied when splitting a node
id::Base.UUID
# a vector holding references to the graph operations involving this node
operations::Vector{Operation}
end
# same as DataTaskNode
@ -23,10 +30,11 @@ struct ComputeTaskNode <: Node
parents::Vector{Node}
children::Vector{Node}
id::Base.UUID
operations::Vector{Operation}
end
DataTaskNode(t::AbstractDataTask) = DataTaskNode(t, Vector{Node}(), Vector{Node}(), UUIDs.uuid1(rng))
ComputeTaskNode(t::AbstractComputeTask) = ComputeTaskNode(t, Vector{Node}(), Vector{Node}(), UUIDs.uuid1(rng))
DataTaskNode(t::AbstractDataTask) = DataTaskNode(t, Vector{Node}(), Vector{Node}(), UUIDs.uuid1(rng), Vector{Operation}())
ComputeTaskNode(t::AbstractComputeTask) = ComputeTaskNode(t, Vector{Node}(), Vector{Node}(), UUIDs.uuid1(rng), Vector{Operation}())
struct Edge
# edge points from child to parent

View File

@ -17,14 +17,6 @@ data(t::AbstractDataTask) = getfield(t, :data)
data(t::AbstractComputeTask) = 0
# define compute_efforts tasks computation
# put some "random" numbers here for now
compute_effort(t::ComputeTaskS1) = 10
compute_effort(t::ComputeTaskS2) = 10
compute_effort(t::ComputeTaskU) = 6
compute_effort(t::ComputeTaskV) = 20
compute_effort(t::ComputeTaskP) = 15
compute_effort(t::ComputeTaskSum) = 1
function compute_effort(t::FusedComputeTask)
(T1, T2) = collect(typeof(t).parameters)
return compute_effort(T1()) + compute_effort(T2())
@ -40,17 +32,6 @@ function compute_intensity(t::AbstractTask)::UInt64
return compute_effort(t) / data(t)
end
function show(io::IO, t::DataTask)
print(io, "Data", t.data)
end
show(io::IO, t::ComputeTaskS1) = print("ComputeS1")
show(io::IO, t::ComputeTaskS2) = print("ComputeS2")
show(io::IO, t::ComputeTaskP) = print("ComputeP")
show(io::IO, t::ComputeTaskU) = print("ComputeU")
show(io::IO, t::ComputeTaskV) = print("ComputeV")
show(io::IO, t::ComputeTaskSum) = print("ComputeSum")
function show(io::IO, t::FusedComputeTask)
(T1, T2) = get_types(t)
print(io, "ComputeFuse(", T1(), ", ", T2(), ")")
@ -68,5 +49,5 @@ function ==(t1::AbstractDataTask, t2::AbstractDataTask)
return data(t1) == data(t2)
end
copy(t::DataTask) = DataTask(t.data)
copy(t::AbstractDataTask) = error("Need to implement copying for your data tasks!")
copy(t::AbstractComputeTask) = typeof(t)()

View File

@ -3,34 +3,6 @@ abstract type AbstractTask end
abstract type AbstractComputeTask <: AbstractTask end
abstract type AbstractDataTask <: AbstractTask end
struct DataTask <: AbstractDataTask
data::UInt64
end
# S task with 1 child
struct ComputeTaskS1 <: AbstractComputeTask
end
# S task with 2 children
struct ComputeTaskS2 <: AbstractComputeTask
end
# P task with 0 children
struct ComputeTaskP <: AbstractComputeTask
end
# v task with 2 children
struct ComputeTaskV <: AbstractComputeTask
end
# u task with 1 child
struct ComputeTaskU <: AbstractComputeTask
end
# task that sums all its inputs, n children
struct ComputeTaskSum <: AbstractComputeTask
end
struct FusedComputeTask{T1<:AbstractComputeTask, T2<:AbstractComputeTask} <: AbstractComputeTask
end

View File

@ -12,7 +12,7 @@ function test_known_graphs()
@test props.compute_effort == 185
@test props.data == 102
@test length(generate_options(g_ABAB).nodeFusions) == 10
@test length(get_operations(g_ABAB).nodeFusions) == 10
test_node_fusion(g_ABAB)
test_random_walk(g_ABAB, 100)
@ -32,7 +32,7 @@ end
function test_node_fusion(g::DAG)
props = graph_properties(g)
options = generate_options(g)
options = get_operations(g)
nodes_number = length(g.nodes)
data = props.data
@ -53,7 +53,7 @@ function test_node_fusion(g::DAG)
data = props.data
compute_effort = props.compute_effort
options = generate_options(g)
options = get_operations(g)
end
end
@ -70,7 +70,7 @@ function test_random_walk(g::DAG, n::Int64)
# choose push or pop
if rand(Bool)
# push
opt = generate_options(g)
opt = get_operations(g)
# choose one of fuse/split/reduce
option = rand(1:3)