More fun with type stability and comment out some asserts that take 95% of the time

This commit is contained in:
Anton Reinhard 2023-11-21 14:04:56 +01:00
parent 705bfb30fe
commit 7d31f61e5f
6 changed files with 57 additions and 37 deletions

View File

@ -46,7 +46,7 @@ Insert the edge between node1 (child) and node2 (parent) into the graph.
See also: [`insert_node!`](@ref), [`remove_node!`](@ref), [`remove_edge!`](@ref)
"""
function insert_edge!(graph::DAG, node1::Node, node2::Node; track = true, invalidate_cache = true)
@assert (node2 parents(node1)) && (node1 children(node2)) "Edge to insert already exists"
#@assert (node2 ∉ parents(node1)) && (node1 ∉ children(node2)) "Edge to insert already exists"
# 1: mute
# edge points from child to parent
@ -85,7 +85,7 @@ Remove the node from the graph.
See also: [`insert_node!`](@ref), [`insert_edge!`](@ref), [`remove_edge!`](@ref)
"""
function remove_node!(graph::DAG, node::Node; track = true, invalidate_cache = true)
@assert node in graph.nodes "Trying to remove a node that's not in the graph"
#@assert node in graph.nodes "Trying to remove a node that's not in the graph"
# 1: mute
delete!(graph.nodes, node)
@ -127,15 +127,15 @@ function remove_edge!(graph::DAG, node1::Node, node2::Node; track = true, invali
filter!(x -> x != node2, node1.parents)
filter!(x -> x != node1, node2.children)
@assert begin
#=@assert begin
removed = pre_length1 - length(node1.parents)
removed <= 1
end "removed more than one node from node1's parents"
end "removed more than one node from node1's parents"=#
@assert begin
#=@assert begin
removed = pre_length2 - length(children(node2))
removed <= 1
end "removed more than one node from node2's children"
end "removed more than one node from node2's children"=#
# 2: keep track
if (track)
@ -163,7 +163,7 @@ function replace_children!(task::FusedComputeTask, before, after)
replacedIn1 = length(findall(x -> x == before, task.t1_inputs))
replacedIn2 = length(findall(x -> x == before, task.t2_inputs))
@assert replacedIn1 >= 1 || replacedIn2 >= 1 "Nothing to replace while replacing $before with $after in $(task.t1_inputs...) and $(task.t2_inputs...)"
#@assert replacedIn1 >= 1 || replacedIn2 >= 1 "Nothing to replace while replacing $before with $after in $(task.t1_inputs...) and $(task.t2_inputs...)"
replace!(task.t1_inputs, before => after)
replace!(task.t2_inputs, before => after)
@ -191,7 +191,7 @@ function update_child!(graph::DAG, n::Node, child_before::Symbol, child_after::S
taskBefore = copy(task(n))
if !((child_before in task(n).t1_inputs) || (child_before in task(n).t2_inputs))
#=if !((child_before in task(n).t1_inputs) || (child_before in task(n).t2_inputs))
println("------------------ Nothing to replace!! ------------------")
child_ids = Vector{String}()
for child in children(n)
@ -199,11 +199,11 @@ function update_child!(graph::DAG, n::Node, child_before::Symbol, child_after::S
end
println("From $(child_before) to $(child_after) in $n with children $(child_ids)")
@assert false
end
end=#
replace_children!(task(n), child_before, child_after)
if !((child_after in task(n).t1_inputs) || (child_after in task(n).t2_inputs))
#=if !((child_after in task(n).t1_inputs) || (child_after in task(n).t2_inputs))
println("------------------ Did not replace anything!! ------------------")
child_ids = Vector{String}()
for child in children(n)
@ -211,7 +211,7 @@ function update_child!(graph::DAG, n::Node, child_before::Symbol, child_after::S
end
println("From $(child_before) to $(child_after) in $n with children $(child_ids)")
@assert false
end
end=#
# keep track
if (track)

View File

@ -24,7 +24,7 @@ To get the set of possible operations, use [`get_operations`](@ref).
The members of the object should not be manually accessed, instead always use the provided interface functions.
"""
mutable struct DAG
nodes::Set{Node}
nodes::Set{Union{DataTaskNode, ComputeTaskNode}}
# The operations currently applied to the set of nodes
appliedOperations::Stack{AppliedOperation}
@ -36,7 +36,7 @@ mutable struct DAG
possibleOperations::PossibleOperations
# The set of nodes whose possible operations need to be reevaluated
dirtyNodes::Set{Node}
dirtyNodes::Set{Union{DataTaskNode, ComputeTaskNode}}
# "snapshot" system: keep track of added/removed nodes/edges since last snapshot
# these are muted in insert_node! etc.

View File

@ -3,35 +3,35 @@
Return the compute effort of an S1 task.
"""
compute_effort(t::ComputeTaskS1) = 11.0
compute_effort(t::ComputeTaskS1)::Float64 = 11.0
"""
compute_effort(t::ComputeTaskS2)
Return the compute effort of an S2 task.
"""
compute_effort(t::ComputeTaskS2) = 12.0
compute_effort(t::ComputeTaskS2)::Float64 = 12.0
"""
compute_effort(t::ComputeTaskU)
Return the compute effort of a U task.
"""
compute_effort(t::ComputeTaskU) = 1.0
compute_effort(t::ComputeTaskU)::Float64 = 1.0
"""
compute_effort(t::ComputeTaskV)
Return the compute effort of a V task.
"""
compute_effort(t::ComputeTaskV) = 6.0
compute_effort(t::ComputeTaskV)::Float64 = 6.0
"""
compute_effort(t::ComputeTaskP)
Return the compute effort of a P task.
"""
compute_effort(t::ComputeTaskP) = 0.0
compute_effort(t::ComputeTaskP)::Float64 = 0.0
"""
compute_effort(t::ComputeTaskSum)
@ -41,7 +41,7 @@ Return the compute effort of a Sum task.
Note: This is a constant compute effort, even though sum scales with the number of its inputs. Since there is only ever a single sum node in a graph generated from the ABC-Model,
this doesn't matter.
"""
compute_effort(t::ComputeTaskSum) = 1.0
compute_effort(t::ComputeTaskSum)::Float64 = 1.0
"""
show(io::IO, t::DataTask)

View File

@ -17,10 +17,12 @@ is_exit_node(node::Node)::Bool = length(parents(node)) == 0
Return the node's task.
"""
function task(node::DataTaskNode{TaskType})::TaskType where {TaskType <: AbstractDataTask}
function task(node::DataTaskNode{TaskType})::TaskType where {TaskType <: Union{AbstractDataTask, AbstractComputeTask}}
return node.task
end
function task(node::ComputeTaskNode{TaskType})::TaskType where {TaskType <: AbstractComputeTask}
function task(
node::ComputeTaskNode{TaskType},
)::TaskType where {TaskType <: Union{AbstractDataTask, AbstractComputeTask}}
return node.task
end

View File

@ -7,6 +7,17 @@ function GraphProperties()
return (data = 0.0, computeEffort = 0.0, computeIntensity = 0.0, noNodes = 0, noEdges = 0)::GraphProperties
end
@inline function _props(
node::DataTaskNode{TaskType},
)::Tuple{Float64, Float64, Int64} where {TaskType <: AbstractDataTask}
return (data(task(node)) * length(parents(node)), 0.0, length(parents(node)))
end
@inline function _props(
node::ComputeTaskNode{TaskType},
)::Tuple{Float64, Float64, Int64} where {TaskType <: AbstractComputeTask}
return (0.0, compute_effort(task(node)), length(parents(node)))
end
"""
GraphProperties(graph::DAG)
@ -20,9 +31,10 @@ function GraphProperties(graph::DAG)
ce = 0.0
ed = 0
for node in graph.nodes
d += data(task(node)) * length(node.parents)
ce += compute_effort(task(node))
ed += length(node.parents)
props = _props(node)
d += props[1]
ce += props[2]
ed += props[3]
end
return (

View File

@ -3,9 +3,9 @@
Helper struct for [`NodeTrie`](@ref). After the Trie's first level, every Trie level contains the vector of nodes that had children up to that level, and the TrieNode's children by UUID of the node's children.
"""
mutable struct NodeIdTrie
value::Vector{Node}
children::Dict{UUID, NodeIdTrie}
mutable struct NodeIdTrie{NodeType <: Node}
value::Vector{NodeType}
children::Dict{UUID, NodeIdTrie{NodeType}}
end
"""
@ -35,8 +35,8 @@ end
Constructor for an empty [`NodeIdTrie`](@ref).
"""
function NodeIdTrie()
return NodeIdTrie(Vector{Node}(), Dict{UUID, NodeIdTrie}())
function NodeIdTrie{NodeType}() where {NodeType <: Node}
return NodeIdTrie(Vector{NodeType}(), Dict{UUID, NodeIdTrie{NodeType}}())
end
"""
@ -44,17 +44,21 @@ end
Insert the given node into the trie. The depth is used to iterate through the trie layers, while the function calls itself recursively until it ran through all children of the node.
"""
function insert_helper!(trie::NodeIdTrie, node::Node, depth::Int)
function insert_helper!(
trie::NodeIdTrie{NodeType},
node::NodeType,
depth::Int,
) where {TaskType <: AbstractTask, NodeType <: Union{DataTaskNode{TaskType}, ComputeTaskNode{TaskType}}}
if (length(children(node)) == depth)
push!(trie.value, node)
return nothing
end
depth = depth + 1
id = children(node)[depth].id
id = node.children[depth].id
if (!haskey(trie.children, id))
trie.children[id] = NodeIdTrie()
trie.children[id] = NodeIdTrie{NodeType}()
end
return insert_helper!(trie.children[id], node, depth)
end
@ -64,12 +68,14 @@ end
Insert the given node into the trie. It's sorted by its type in the first layer, then by its children in the following layers.
"""
function insert!(trie::NodeTrie, node::Node)
t = typeof(task(node))
if (!haskey(trie.children, t))
trie.children[t] = NodeIdTrie()
function insert!(
trie::NodeTrie,
node::NodeType,
) where {TaskType <: AbstractTask, NodeType <: Union{DataTaskNode{TaskType}, ComputeTaskNode{TaskType}}}
if (!haskey(trie.children, NodeType))
trie.children[NodeType] = NodeIdTrie{NodeType}()
end
return insert_helper!(trie.children[typeof(task(node))], node, 0)
return insert_helper!(trie.children[NodeType], node, 0)
end
"""