Skip to content

Commit 923348e

Browse files
author
Damian Rouson
authored
Merge pull request #57 from sourceryinstitute/concurrent-topo-sort
Simplified concurrent topological sort
2 parents 1dd4eab + 6e6387c commit 923348e

File tree

1 file changed

+28
-30
lines changed

1 file changed

+28
-30
lines changed

src/dag_s.f90

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
implicit none
1616

17+
type searched_and_ordered_t
18+
integer, allocatable, dimension(:) :: s, o
19+
end type
20+
1721
contains
1822

1923
module procedure construct_from_components
@@ -30,50 +34,44 @@ pure module function topological_sort(dag) result(order)
3034
call assert(all(dag%vertices(:)%edges_allocated()), "dag_s topological_sort: all(dag%vertices(:)%edges_allocated())")
3135

3236
block
33-
integer, allocatable :: discovered(:), searched(:)
37+
type(searched_and_ordered_t) searched_and_ordered
3438
integer v
3539

36-
allocate(discovered(0), order(0), searched(0))
40+
searched_and_ordered = searched_and_ordered_t(s = [integer::], o = [integer::])
3741

38-
do v = 1, size(dag%vertices)
39-
if (.not. any(v == searched)) then
40-
call depth_first_search(v, [integer::], searched, order)
41-
discovered = [discovered, searched]
42-
searched = discovered
43-
end if
42+
do concurrent(v = 1:size(dag%vertices))
43+
if (.not. any(v == searched_and_ordered%s)) &
44+
searched_and_ordered = depth_first_search(v, [integer::], searched_and_ordered%o)
4445
end do
46+
order = searched_and_ordered%o
4547
end block
4648

4749
contains
4850

49-
pure recursive subroutine depth_first_search(v, d, s, o)
50-
integer, intent(in) :: v, d(:)
51-
integer, intent(out), allocatable :: s(:)
52-
integer, intent(inout), allocatable :: o(:)
51+
pure recursive function depth_first_search(v, d, o) result(hybrid)
52+
integer, intent(in) :: v
53+
integer, intent(in), dimension(:) :: d, o
54+
type(searched_and_ordered_t) hybrid
5355

5456
call assert(.not. any(v == d), "depth_first_search: cycle detected", intrinsic_array_t([v,d]))
5557

56-
block
57-
integer, allocatable :: dependencies(:), s_local(:), d_local(:)
58-
integer w
59-
60-
dependencies = dag%depends_on(v)
58+
hybrid = searched_and_ordered_t(s = [integer::], o = o)
6159

62-
allocate(s_local(0), d_local(0))
60+
associate(dependencies => dag%depends_on(v))
61+
block
62+
integer w
63+
do concurrent(w = 1:size(dependencies))
64+
associate(w_dependencies => dependencies(w))
65+
if (.not. any(w_dependencies == hybrid%s)) hybrid = depth_first_search(w_dependencies, [d, v], hybrid%o)
66+
end associate
67+
end do
68+
end block
69+
end associate
6370

64-
do w = 1, size(dependencies)
65-
if (.not. any(dependencies(w) == s_local)) then
66-
call depth_first_search(dependencies(w), [d, v], s_local, o)
67-
d_local = [d_local, s_local]
68-
s_local = d_local
69-
end if
70-
end do
71-
72-
if (.not. any(v == o)) o = [v, o]
73-
s = [v, s_local]
74-
end block
71+
if (.not. any(v == hybrid%o)) hybrid%o = [v, hybrid%o]
72+
hybrid = searched_and_ordered_t(s = [v, hybrid%s], o = hybrid%o)
7573

76-
end subroutine
74+
end function
7775

7876
end function topological_sort
7977

0 commit comments

Comments
 (0)