Skip to content

Commit

Permalink
don't bother sorting dag
Browse files Browse the repository at this point in the history
  • Loading branch information
everythingfunctional committed Aug 9, 2023
1 parent 557c5b8 commit 6b22731
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 97 deletions.
93 changes: 0 additions & 93 deletions src/dag_m.f90
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,11 @@ module dag_m
type :: dag_t
!! Encapsulate a graph as an array of vertices, each storing dependency information
type(vertex_t), allocatable :: vertices(:)
integer, allocatable :: order(:)
contains
procedure :: is_sorted_and_acyclic
procedure :: num_vertices
procedure :: dependencies_for
procedure :: depends_on
end type

type searched_and_ordered_t
integer, allocatable, dimension(:) :: s, o
end type

interface dag_t
module procedure construct_from_vertices
end interface
Expand All @@ -37,47 +30,6 @@ function construct_from_vertices(vertices) result(dag)
type(dag_t) dag

dag%vertices = vertices
dag%order = topological_sort(dag)
end function

elemental function is_sorted_and_acyclic(self)
!! Result is true if dag%order contains a topological sorting of vertex identifiers
class(dag_t), intent(in) :: self
logical is_sorted_and_acyclic

if (.not. allocated(self%order)) then
is_sorted_and_acyclic = .false.
return
end if

associate(num_vertices => size(self%vertices), order_size => size(self%order))

block
integer i, j

do i = 1, num_vertices
associate(edges => self%vertices(self%order(i))%edges)
do j = 1, size(edges)
if (.not. any(edges(j) == self%order(1:i))) then
is_sorted_and_acyclic = .false.
return
end if
end do
end associate
end do

is_sorted_and_acyclic = .true.
end block

end associate
end function

elemental function num_vertices(self)
!! Result is the size of the vertex array
class(dag_t), intent(in) :: self
integer num_vertices

num_vertices = size(self%vertices)
end function

pure function depends_on(self, vertex_num) result(dependencies)
Expand Down Expand Up @@ -105,49 +57,4 @@ pure function dependencies_for(self, vertex_id) result(dependency_ids)

dependency_ids = self%vertices(vertex_id)%edges
end function

pure function topological_sort(dag) result(order)
!! Provide array of vertex numbers ordered in a way that respects dependencies
type(dag_t), intent(in) :: dag
integer, allocatable :: order(:)

block
type(searched_and_ordered_t) searched_and_ordered
integer v

searched_and_ordered = searched_and_ordered_t(s = [integer::], o = [integer::])

do v = 1, size(dag%vertices)
if (.not. any(v == searched_and_ordered%s)) &
searched_and_ordered = depth_first_search(dag, v, [integer::], searched_and_ordered%o)
end do
order = searched_and_ordered%o
end block

end function topological_sort

pure recursive function depth_first_search(dag, v, d, o) result(hybrid)
type(dag_t), intent(in) :: dag
integer, intent(in) :: v
integer, intent(in), dimension(:) :: d, o
type(searched_and_ordered_t) hybrid

hybrid = searched_and_ordered_t(s = [integer::], o = o)

associate(dependencies => dag%depends_on(v))
block
integer w
do w = 1, size(dependencies)
associate(w_dependencies => dependencies(w))
if (.not. any(w_dependencies == hybrid%s)) hybrid = depth_first_search(dag, w_dependencies, [d, v], hybrid%o)
end associate
end do
end block
end associate

if (.not. any(v == hybrid%o)) hybrid%o = [v, hybrid%o]
hybrid = searched_and_ordered_t(s = [v, hybrid%s], o = hybrid%o)

end function

end module dag_m
23 changes: 19 additions & 4 deletions src/runner_m.f90
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,30 @@ subroutine run_single_image(dag)
type(dag_t), intent(in) :: dag

type(payload_t), allocatable :: results(:)
integer :: i
logical, allocatable :: done(:)

associate(num_tasks => size(dag%vertices))
allocate(results(num_tasks))
do i = 1, size(dag%vertices)
associate(next_task => dag%order(i))
allocate(results(num_tasks), done(num_tasks))
done = .false.
do while (.not. all(done))
associate(next_task => find_next_task())
results(next_task) = dag%vertices(next_task)%task%execute(results(dag%dependencies_for(next_task)))
done(next_task) = .true.
end associate
end do
end associate
contains
pure function find_next_task() result(next_task)
integer :: next_task

integer :: task

do task = 1, size(dag%vertices)
if (.not.done(task) .and. all(done(dag%dependencies_for(task)))) then
next_task = task
return
end if
end do
end function
end subroutine
end module

0 comments on commit 6b22731

Please sign in to comment.