Shuffle files and functions around for more consistent naming and smaller files
This commit is contained in:
15
src/node/compare.jl
Normal file
15
src/node/compare.jl
Normal file
@@ -0,0 +1,15 @@
|
||||
function ==(e1::Edge, e2::Edge)
|
||||
return e1.edge[1] == e2.edge[1] && e1.edge[2] == e2.edge[2]
|
||||
end
|
||||
|
||||
function ==(n1::Node, n2::Node)
|
||||
return false
|
||||
end
|
||||
|
||||
function ==(n1::ComputeTaskNode, n2::ComputeTaskNode)
|
||||
return n1.id == n2.id
|
||||
end
|
||||
|
||||
function ==(n1::DataTaskNode, n2::DataTaskNode)
|
||||
return n1.id == n2.id
|
||||
end
|
23
src/node/create.jl
Normal file
23
src/node/create.jl
Normal file
@@ -0,0 +1,23 @@
|
||||
function make_node(t::AbstractTask)
|
||||
error("Cannot make a node from this task type")
|
||||
end
|
||||
|
||||
function make_node(t::AbstractDataTask)
|
||||
return DataTaskNode(t)
|
||||
end
|
||||
|
||||
function make_node(t::AbstractComputeTask)
|
||||
return ComputeTaskNode(t)
|
||||
end
|
||||
|
||||
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((n1, n2))
|
||||
end
|
||||
|
||||
function make_edge(n1::DataTaskNode, n2::ComputeTaskNode)
|
||||
return Edge((n1, n2))
|
||||
end
|
7
src/node/print.jl
Normal file
7
src/node/print.jl
Normal file
@@ -0,0 +1,7 @@
|
||||
function show(io::IO, n::Node)
|
||||
print(io, "Node(", n.task, ")")
|
||||
end
|
||||
|
||||
function show(io::IO, e::Edge)
|
||||
print(io, "Edge(", e.edge[1], ", ", e.edge[2], ")")
|
||||
end
|
52
src/node/properties.jl
Normal file
52
src/node/properties.jl
Normal file
@@ -0,0 +1,52 @@
|
||||
is_entry_node(node::Node) = length(node.children) == 0
|
||||
is_exit_node(node::Node) = length(node.parents) == 0
|
||||
|
||||
# children = prerequisite nodes, nodes that need to execute before the task, edges point into this task
|
||||
function children(node::Node)
|
||||
return copy(node.children)
|
||||
end
|
||||
|
||||
# parents = subsequent nodes, nodes that need this node to execute, edges point from this task
|
||||
function parents(node::Node)
|
||||
return copy(node.parents)
|
||||
end
|
||||
|
||||
# siblings = all children of any parents, no duplicates, includes the node itself
|
||||
function siblings(node::Node)
|
||||
result = Set{Node}()
|
||||
push!(result, node)
|
||||
for parent in node.parents
|
||||
union!(result, parent.children)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
# partners = all parents of any children, no duplicates, includes the node itself
|
||||
function partners(node::Node)
|
||||
result = Set{Node}()
|
||||
push!(result, node)
|
||||
for child in node.children
|
||||
union!(result, child.parents)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
# alternative version to partners(Node), avoiding allocation of a new set
|
||||
# works on the given set and returns nothing
|
||||
function partners(node::Node, set::Set{Node})
|
||||
push!(set, node)
|
||||
for child in node.children
|
||||
union!(set, child.parents)
|
||||
end
|
||||
return nothing
|
||||
end
|
||||
|
||||
function is_parent(potential_parent, node)
|
||||
return potential_parent in node.parents
|
||||
end
|
||||
|
||||
function is_child(potential_child, node)
|
||||
return potential_child in node.children
|
||||
end
|
60
src/node/type.jl
Normal file
60
src/node/type.jl
Normal file
@@ -0,0 +1,60 @@
|
||||
using Random
|
||||
using UUIDs
|
||||
using Base.Threads
|
||||
|
||||
# TODO: reliably find out how many threads we're running with (nthreads() returns 1 when precompiling :/)
|
||||
rng = [Random.MersenneTwister(0) for _ in 1:32]
|
||||
|
||||
abstract type Node end
|
||||
|
||||
# declare this type here because it's needed
|
||||
# the specific operations are declared in graph.jl
|
||||
abstract type Operation end
|
||||
|
||||
mutable struct DataTaskNode <: Node
|
||||
task::AbstractDataTask
|
||||
|
||||
# use vectors as sets have way too much memory overhead
|
||||
parents::Vector{Node}
|
||||
children::Vector{Node}
|
||||
|
||||
# need a unique identifier unique to every *constructed* node
|
||||
# however, it can be copied when splitting a node
|
||||
id::Base.UUID
|
||||
|
||||
# the NodeReduction involving this node, if it exists
|
||||
# Can't use the NodeReduction type here because it's not yet defined
|
||||
nodeReduction::Union{Operation, Missing}
|
||||
|
||||
# the NodeSplit involving this node, if it exists
|
||||
nodeSplit::Union{Operation, Missing}
|
||||
|
||||
# the node fusion involving this node, if it exists
|
||||
nodeFusion::Union{Operation, Missing}
|
||||
end
|
||||
|
||||
# same as DataTaskNode
|
||||
mutable struct ComputeTaskNode <: Node
|
||||
task::AbstractComputeTask
|
||||
parents::Vector{Node}
|
||||
children::Vector{Node}
|
||||
id::Base.UUID
|
||||
|
||||
nodeReduction::Union{Operation, Missing}
|
||||
nodeSplit::Union{Operation, Missing}
|
||||
|
||||
# for ComputeTasks there can be multiple fusions, unlike the DataTasks
|
||||
nodeFusions::Vector{Operation}
|
||||
end
|
||||
|
||||
DataTaskNode(t::AbstractDataTask) = DataTaskNode(t, Vector{Node}(), Vector{Node}(), UUIDs.uuid1(rng[threadid()]), missing, missing, missing)
|
||||
ComputeTaskNode(t::AbstractComputeTask) = ComputeTaskNode(t, Vector{Node}(), Vector{Node}(), UUIDs.uuid1(rng[threadid()]), missing, missing, Vector{NodeFusion}())
|
||||
|
||||
struct Edge
|
||||
# edge points from child to parent
|
||||
edge::Union{Tuple{DataTaskNode, ComputeTaskNode}, Tuple{ComputeTaskNode, DataTaskNode}}
|
||||
end
|
||||
|
||||
copy(m::Missing) = missing
|
||||
copy(n::ComputeTaskNode) = ComputeTaskNode(copy(n.task), copy(n.parents), copy(n.children), UUIDs.uuid1(rng[threadid()]), copy(n.nodeReduction), copy(n.nodeSplit), copy(n.nodeFusions))
|
||||
copy(n::DataTaskNode) = DataTaskNode(copy(n.task), copy(n.parents), copy(n.children), UUIDs.uuid1(rng[threadid()]), copy(n.nodeReduction), copy(n.nodeSplit), copy(n.nodeFusion))
|
43
src/node/validate.jl
Normal file
43
src/node/validate.jl
Normal file
@@ -0,0 +1,43 @@
|
||||
function is_valid_node(graph::DAG, node::Node)
|
||||
@assert node in graph "Node is not part of the given graph!"
|
||||
|
||||
for parent in node.parents
|
||||
@assert typeof(parent) != typeof(node) "Node's type is the same as its parent's!"
|
||||
@assert parent in graph "Node's parent is not in the same graph!"
|
||||
@assert node in parent.children "Node is not a child of its parent!"
|
||||
end
|
||||
|
||||
for child in node.children
|
||||
@assert typeof(child) != typeof(node) "Node's type is the same as its child's!"
|
||||
@assert child in graph "Node's child is not in the same graph!"
|
||||
@assert node in child.parents "Node is not a parent of its child!"
|
||||
end
|
||||
|
||||
if !ismissing(node.nodeReduction)
|
||||
@assert is_valid(graph, node.nodeReduction)
|
||||
end
|
||||
if !ismissing(node.nodeSplit)
|
||||
@assert is_valid(graph, node.nodeSplit)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# call with @assert
|
||||
function is_valid(graph::DAG, node::ComputeTaskNode)
|
||||
@assert is_valid_node(graph, node)
|
||||
|
||||
for nf in node.nodeFusions
|
||||
@assert is_valid(graph, nf)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# call with @assert
|
||||
function is_valid(graph::DAG, node::DataTaskNode)
|
||||
@assert is_valid_node(graph, node)
|
||||
|
||||
if !ismissing(node.nodeFusion)
|
||||
@assert is_valid(graph, node.nodeFusion)
|
||||
end
|
||||
return true
|
||||
end
|
Reference in New Issue
Block a user