Skip to content

Commit 9cfc6d8

Browse files
committed
Add GraphsSharedArraysExt and remove Distributed dependency
1 parent b5da85a commit 9cfc6d8

File tree

12 files changed

+211
-139
lines changed

12 files changed

+211
-139
lines changed

Project.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ version = "1.13.1"
55
[deps]
66
ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d"
77
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
8-
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
98
Inflate = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
109
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1110
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
12-
SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
1311
SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
1412
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1513
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1614

15+
[weakdeps]
16+
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
17+
SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
18+
19+
[extensions]
20+
GraphsSharedArraysExt = "SharedArrays"
21+
1722
[compat]
1823
ArnoldiMethod = "0.4"
1924
Distributed = "1"
@@ -25,4 +30,4 @@ SharedArrays = "1"
2530
SimpleTraits = "0.9"
2631
SparseArrays = "1"
2732
Statistics = "1"
28-
julia = "1.10"
33+
julia = "1.10"

ext/GraphsSharedArraysExt.jl

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
module GraphsSharedArraysExt
2+
3+
using Graphs
4+
using SharedArrays: SharedArrays, SharedMatrix, SharedVector, sdata
5+
using SharedArrays.Distributed: @distributed
6+
using Random: shuffle
7+
8+
# betweenness
9+
function Graphs.Parallel.distr_betweenness_centrality(
10+
g::AbstractGraph,
11+
vs=vertices(g),
12+
distmx::AbstractMatrix=weights(g);
13+
normalize=true,
14+
endpoints=false,
15+
)::Vector{Float64}
16+
n_v = nv(g)
17+
k = length(vs)
18+
isdir = is_directed(g)
19+
20+
# Parallel reduction
21+
22+
betweenness = @distributed (+) for s in vs
23+
temp_betweenness = zeros(n_v)
24+
if degree(g, s) > 0 # this might be 1?
25+
state = Graphs.dijkstra_shortest_paths(
26+
g, s, distmx; allpaths=true, trackvertices=true
27+
)
28+
if endpoints
29+
Graphs._accumulate_endpoints!(temp_betweenness, state, g, s)
30+
else
31+
Graphs._accumulate_basic!(temp_betweenness, state, g, s)
32+
end
33+
end
34+
temp_betweenness
35+
end
36+
37+
Graphs._rescale!(betweenness, n_v, normalize, isdir, k)
38+
39+
return betweenness
40+
end
41+
42+
# closeness
43+
function Graphs.Parallel.distr_closeness_centrality(
44+
g::AbstractGraph, distmx::AbstractMatrix=weights(g); normalize=true
45+
)::Vector{Float64}
46+
n_v = Int(nv(g))
47+
closeness = SharedVector{Float64}(n_v)
48+
fill!(closeness, 0.0)
49+
50+
@sync @distributed for u in vertices(g)
51+
if degree(g, u) == 0 # no need to do Dijkstra here
52+
closeness[u] = 0.0
53+
else
54+
d = Graphs.dijkstra_shortest_paths(g, u, distmx).dists
55+
δ = filter(x -> x != typemax(x), d)
56+
σ = sum(δ)
57+
l = length(δ) - 1
58+
if σ > 0
59+
closeness[u] = l / σ
60+
if normalize
61+
n = l * 1.0 / (n_v - 1)
62+
closeness[u] *= n
63+
end
64+
else
65+
closeness[u] = 0.0
66+
end
67+
end
68+
end
69+
return sdata(closeness)
70+
end
71+
72+
# radiality
73+
function Graphs.Parallel.distr_radiality_centrality(g::AbstractGraph)::Vector{Float64}
74+
n_v = nv(g)
75+
vs = vertices(g)
76+
n = ne(g)
77+
meandists = SharedVector{Float64}(Int(n_v))
78+
maxdists = SharedVector{Float64}(Int(n_v))
79+
80+
@sync @distributed for i in 1:n_v
81+
d = Graphs.dijkstra_shortest_paths(g, vs[i])
82+
maxdists[i] = maximum(d.dists)
83+
meandists[i] = sum(d.dists) / (n_v - 1)
84+
nothing
85+
end
86+
dmtr = maximum(maxdists)
87+
radialities = collect(meandists)
88+
return ((dmtr + 1) .- radialities) ./ dmtr
89+
end
90+
91+
# stress
92+
function Graphs.Parallel.distr_stress_centrality(
93+
g::AbstractGraph, vs=vertices(g)
94+
)::Vector{Int64}
95+
n_v = nv(g)
96+
k = length(vs)
97+
isdir = is_directed(g)
98+
99+
# Parallel reduction
100+
stress = @distributed (+) for s in vs
101+
temp_stress = zeros(Int64, n_v)
102+
if degree(g, s) > 0 # this might be 1?
103+
state = Graphs.dijkstra_shortest_paths(g, s; allpaths=true, trackvertices=true)
104+
Graphs._stress_accumulate_basic!(temp_stress, state, g, s)
105+
end
106+
temp_stress
107+
end
108+
return stress
109+
end
110+
111+
# generate_reduce
112+
function Graphs.Parallel.distr_generate_reduce(
113+
g::AbstractGraph{T}, gen_func::Function, comp::Comp, reps::Integer
114+
) where {T<:Integer,Comp}
115+
# Type assert required for type stability
116+
min_set::Vector{T} = @distributed ((x, y) -> comp(x, y) ? x : y) for _ in 1:reps
117+
gen_func(g)
118+
end
119+
return min_set
120+
end
121+
122+
# eccentricity
123+
function Graphs.Parallel.distr_eccentricity(
124+
g::AbstractGraph, vs=vertices(g), distmx::AbstractMatrix{T}=weights(g)
125+
) where {T<:Number}
126+
vlen = length(vs)
127+
eccs = SharedVector{T}(vlen)
128+
@sync @distributed for i in 1:vlen
129+
local d = Graphs.dijkstra_shortest_paths(g, vs[i], distmx)
130+
eccs[i] = maximum(d.dists)
131+
end
132+
d = sdata(eccs)
133+
maximum(d) == typemax(T) && @warn("Infinite path length detected")
134+
return d
135+
end
136+
137+
# dijkstra shortest paths
138+
function Graphs.Parallel.distr_dijkstra_shortest_paths(
139+
g::AbstractGraph{U}, sources=vertices(g), distmx::AbstractMatrix{T}=weights(g)
140+
) where {T<:Number} where {U}
141+
n_v = nv(g)
142+
r_v = length(sources)
143+
144+
# TODO: remove `Int` once julialang/#23029 / #23032 are resolved
145+
dists = SharedMatrix{T}(Int(r_v), Int(n_v))
146+
parents = SharedMatrix{U}(Int(r_v), Int(n_v))
147+
148+
@sync @distributed for i in 1:r_v
149+
state = Graphs.dijkstra_shortest_paths(g, sources[i], distmx)
150+
dists[i, :] = state.dists
151+
parents[i, :] = state.parents
152+
end
153+
154+
result = Graphs.Parallel.MultipleDijkstraState(sdata(dists), sdata(parents))
155+
return result
156+
end
157+
158+
# random greedy color
159+
function Graphs.Parallel.distr_random_greedy_color(
160+
g::AbstractGraph{T}, reps::Integer
161+
) where {T<:Integer}
162+
best = @distributed (Graphs.best_color) for i in 1:reps
163+
seq = shuffle(vertices(g))
164+
Graphs.perm_greedy_color(g, seq)
165+
end
166+
167+
return convert(Graphs.Coloring{T}, best)
168+
end
169+
170+
end

src/Parallel/Parallel.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ module Parallel
22

33
using Graphs
44
using Graphs: sample, AbstractPathState, JohnsonState, BellmanFordState, FloydWarshallState
5-
using Distributed: @distributed
65
using Base.Threads: @threads, nthreads, Atomic, atomic_add!, atomic_cas!
7-
using SharedArrays: SharedMatrix, SharedVector, sdata
86
using ArnoldiMethod: LM, SR, LR, partialschur, partialeigen
97
using Random: AbstractRNG, shuffle
108
import SparseArrays: sparse

src/Parallel/centrality/betweenness.jl

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -39,37 +39,10 @@ function betweenness_centrality(
3939
end
4040
end
4141

42-
function distr_betweenness_centrality(
43-
g::AbstractGraph,
44-
vs=vertices(g),
45-
distmx::AbstractMatrix=weights(g);
46-
normalize=true,
47-
endpoints=false,
48-
)::Vector{Float64}
49-
n_v = nv(g)
50-
k = length(vs)
51-
isdir = is_directed(g)
52-
53-
# Parallel reduction
54-
55-
betweenness = @distributed (+) for s in vs
56-
temp_betweenness = zeros(n_v)
57-
if degree(g, s) > 0 # this might be 1?
58-
state = Graphs.dijkstra_shortest_paths(
59-
g, s, distmx; allpaths=true, trackvertices=true
60-
)
61-
if endpoints
62-
Graphs._accumulate_endpoints!(temp_betweenness, state, g, s)
63-
else
64-
Graphs._accumulate_basic!(temp_betweenness, state, g, s)
65-
end
66-
end
67-
temp_betweenness
68-
end
69-
70-
Graphs._rescale!(betweenness, n_v, normalize, isdir, k)
71-
72-
return betweenness
42+
function distr_betweenness_centrality(args...; kwargs...)
43+
return error(
44+
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
45+
)
7346
end
7447

7548
function distr_betweenness_centrality(

src/Parallel/centrality/closeness.jl

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,10 @@ function closeness_centrality(
1111
end
1212
end
1313

14-
function distr_closeness_centrality(
15-
g::AbstractGraph, distmx::AbstractMatrix=weights(g); normalize=true
16-
)::Vector{Float64}
17-
n_v = Int(nv(g))
18-
closeness = SharedVector{Float64}(n_v)
19-
fill!(closeness, 0.0)
20-
21-
@sync @distributed for u in vertices(g)
22-
if degree(g, u) == 0 # no need to do Dijkstra here
23-
closeness[u] = 0.0
24-
else
25-
d = Graphs.dijkstra_shortest_paths(g, u, distmx).dists
26-
δ = filter(x -> x != typemax(x), d)
27-
σ = sum(δ)
28-
l = length(δ) - 1
29-
if σ > 0
30-
closeness[u] = l / σ
31-
if normalize
32-
n = l * 1.0 / (n_v - 1)
33-
closeness[u] *= n
34-
end
35-
else
36-
closeness[u] = 0.0
37-
end
38-
end
39-
end
40-
return sdata(closeness)
14+
function distr_closeness_centrality(args...; kwargs...)
15+
return error(
16+
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
17+
)
4118
end
4219

4320
function threaded_closeness_centrality(

src/Parallel/centrality/radiality.jl

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,10 @@ function radiality_centrality(g::AbstractGraph; parallel=:distributed)
66
end
77
end
88

9-
function distr_radiality_centrality(g::AbstractGraph)::Vector{Float64}
10-
n_v = nv(g)
11-
vs = vertices(g)
12-
n = ne(g)
13-
meandists = SharedVector{Float64}(Int(n_v))
14-
maxdists = SharedVector{Float64}(Int(n_v))
15-
16-
@sync @distributed for i in 1:n_v
17-
d = Graphs.dijkstra_shortest_paths(g, vs[i])
18-
maxdists[i] = maximum(d.dists)
19-
meandists[i] = sum(d.dists) / (n_v - 1)
20-
nothing
21-
end
22-
dmtr = maximum(maxdists)
23-
radialities = collect(meandists)
24-
return ((dmtr + 1) .- radialities) ./ dmtr
9+
function distr_radiality_centrality(args...; kwargs...)
10+
return error(
11+
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
12+
)
2513
end
2614

2715
function threaded_radiality_centrality(g::AbstractGraph)::Vector{Float64}

src/Parallel/centrality/stress.jl

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,10 @@ function stress_centrality(
2121
end
2222
end
2323

24-
function distr_stress_centrality(g::AbstractGraph, vs=vertices(g))::Vector{Int64}
25-
n_v = nv(g)
26-
k = length(vs)
27-
isdir = is_directed(g)
28-
29-
# Parallel reduction
30-
stress = @distributed (+) for s in vs
31-
temp_stress = zeros(Int64, n_v)
32-
if degree(g, s) > 0 # this might be 1?
33-
state = Graphs.dijkstra_shortest_paths(g, s; allpaths=true, trackvertices=true)
34-
Graphs._stress_accumulate_basic!(temp_stress, state, g, s)
35-
end
36-
temp_stress
37-
end
38-
return stress
24+
function distr_stress_centrality(args...; kwargs...)
25+
return error(
26+
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
27+
)
3928
end
4029

4130
function threaded_stress_centrality(g::AbstractGraph, vs=vertices(g))::Vector{Int64}

src/Parallel/distance.jl

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,10 @@ function eccentricity(
1919
end
2020
end
2121

22-
function distr_eccentricity(
23-
g::AbstractGraph, vs=vertices(g), distmx::AbstractMatrix{T}=weights(g)
24-
) where {T<:Number}
25-
vlen = length(vs)
26-
eccs = SharedVector{T}(vlen)
27-
@sync @distributed for i in 1:vlen
28-
local d = Graphs.dijkstra_shortest_paths(g, vs[i], distmx)
29-
eccs[i] = maximum(d.dists)
30-
end
31-
d = sdata(eccs)
32-
maximum(d) == typemax(T) && @warn("Infinite path length detected")
33-
return d
22+
function distr_eccentricity(args...; kwargs...)
23+
return error(
24+
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
25+
)
3426
end
3527

3628
function threaded_eccentricity(

src/Parallel/shortestpaths/dijkstra.jl

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,8 @@ function threaded_dijkstra_shortest_paths(
5656
return result
5757
end
5858

59-
function distr_dijkstra_shortest_paths(
60-
g::AbstractGraph{U}, sources=vertices(g), distmx::AbstractMatrix{T}=weights(g)
61-
) where {T<:Number} where {U}
62-
n_v = nv(g)
63-
r_v = length(sources)
64-
65-
# TODO: remove `Int` once julialang/#23029 / #23032 are resolved
66-
dists = SharedMatrix{T}(Int(r_v), Int(n_v))
67-
parents = SharedMatrix{U}(Int(r_v), Int(n_v))
68-
69-
@sync @distributed for i in 1:r_v
70-
state = Graphs.dijkstra_shortest_paths(g, sources[i], distmx)
71-
dists[i, :] = state.dists
72-
parents[i, :] = state.parents
73-
end
74-
75-
result = MultipleDijkstraState(sdata(dists), sdata(parents))
76-
return result
59+
function distr_dijkstra_shortest_paths(args...; kwargs...)
60+
return error(
61+
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
62+
)
7763
end

0 commit comments

Comments
 (0)