Skip to content

Commit edad898

Browse files
committed
Add GraphsSharedArraysExt and remove Distributed dependency
1 parent cbda59e commit edad898

File tree

13 files changed

+216
-138
lines changed

13 files changed

+216
-138
lines changed

Project.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ version = "1.12.1"
66
ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d"
77
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
88
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
9-
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
109
Inflate = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
1110
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1211
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
@@ -15,6 +14,12 @@ SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
1514
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1615
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1716

17+
[weakdeps]
18+
SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
19+
20+
[extensions]
21+
GraphsSharedArraysExt = "SharedArrays"
22+
1823
[compat]
1924
Aqua = "0.6"
2025
ArnoldiMethod = "0.4"
@@ -32,17 +37,19 @@ julia = "1.6"
3237
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
3338
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
3439
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
40+
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
3541
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3642
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
3743
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
3844
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
3945
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
4046
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
47+
SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
4148
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
4249
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
4350
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
4451
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
4552
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
4653

4754
[targets]
48-
test = ["Aqua", "Base64", "DelimitedFiles", "Documenter", "JET", "JuliaFormatter", "LinearAlgebra", "Pkg", "Random", "SparseArrays", "StableRNGs", "Statistics", "Test", "Unitful"]
55+
test = ["Aqua", "Base64", "DelimitedFiles", "Distributed", "Documenter", "JET", "JuliaFormatter", "LinearAlgebra", "Pkg", "Random", "SharedArrays", "SparseArrays", "StableRNGs", "Statistics", "Test", "Unitful"]

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+
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/Graphs.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,5 +560,9 @@ include("Experimental/Experimental.jl")
560560
include("Parallel/Parallel.jl")
561561
include("Test/Test.jl")
562562

563+
if !isdefined(Base, :get_extension)
564+
include("../ext/GraphsSharedArraysExt.jl")
565+
end
566+
563567
using .LinAlg
564568
end # module

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
@@ -17,18 +17,10 @@ function eccentricity(
1717
end
1818
end
1919

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

3426
function threaded_eccentricity(

0 commit comments

Comments
 (0)