Skip to content

Add GraphsSharedArraysExt and remove Distributed dependency #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ version = "1.12.1"
ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
Inflate = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Expand All @@ -15,6 +14,12 @@ SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[weakdeps]
SharedArrays = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
Comment on lines +17 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't SharedArrays then be removed from the [deps] section above as well?


[extensions]
GraphsSharedArraysExt = "SharedArrays"

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

[targets]
test = ["Aqua", "Base64", "DelimitedFiles", "Documenter", "JET", "JuliaFormatter", "LinearAlgebra", "Pkg", "Random", "SparseArrays", "StableRNGs", "Statistics", "Test", "Unitful"]
test = ["Aqua", "Base64", "DelimitedFiles", "Distributed", "Documenter", "JET", "JuliaFormatter", "LinearAlgebra", "Pkg", "Random", "SharedArrays", "SparseArrays", "StableRNGs", "Statistics", "Test", "Unitful"]
170 changes: 170 additions & 0 deletions ext/GraphsSharedArraysExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
module GraphsSharedArraysExt

using Graphs
using SharedArrays: SharedArrays, SharedMatrix, SharedVector, sdata
using SharedArrays.Distributed: @distributed
using Random: shuffle

# betweenness
function Graphs.Parallel.distr_betweenness_centrality(
g::AbstractGraph,
vs=vertices(g),
distmx::AbstractMatrix=weights(g);
normalize=true,
endpoints=false,
)::Vector{Float64}
n_v = nv(g)
k = length(vs)
isdir = is_directed(g)

# Parallel reduction

betweenness = @distributed (+) for s in vs
temp_betweenness = zeros(n_v)
if degree(g, s) > 0 # this might be 1?
state = Graphs.dijkstra_shortest_paths(
g, s, distmx; allpaths=true, trackvertices=true
)
if endpoints
Graphs._accumulate_endpoints!(temp_betweenness, state, g, s)
else
Graphs._accumulate_basic!(temp_betweenness, state, g, s)
end
end
temp_betweenness
end

Graphs._rescale!(betweenness, n_v, normalize, isdir, k)

return betweenness
end

# closeness
function Graphs.Parallel.distr_closeness_centrality(
g::AbstractGraph, distmx::AbstractMatrix=weights(g); normalize=true
)::Vector{Float64}
n_v = Int(nv(g))
closeness = SharedVector{Float64}(n_v)
fill!(closeness, 0.0)

@sync @distributed for u in vertices(g)
if degree(g, u) == 0 # no need to do Dijkstra here
closeness[u] = 0.0
else
d = Graphs.dijkstra_shortest_paths(g, u, distmx).dists
δ = filter(x -> x != typemax(x), d)
σ = sum(δ)
l = length(δ) - 1
if σ > 0
closeness[u] = l / σ
if normalize
n = l * 1.0 / (n_v - 1)
closeness[u] *= n
end
else
closeness[u] = 0.0
end
end
end
return sdata(closeness)
end

# radiality
function Graphs.Parallel.distr_radiality_centrality(g::AbstractGraph)::Vector{Float64}
n_v = nv(g)
vs = vertices(g)
n = ne(g)
meandists = SharedVector{Float64}(Int(n_v))
maxdists = SharedVector{Float64}(Int(n_v))

@sync @distributed for i in 1:n_v
d = Graphs.dijkstra_shortest_paths(g, vs[i])
maxdists[i] = maximum(d.dists)
meandists[i] = sum(d.dists) / (n_v - 1)
nothing
end
dmtr = maximum(maxdists)
radialities = collect(meandists)
return ((dmtr + 1) .- radialities) ./ dmtr
end

# stress
function Graphs.Parallel.distr_stress_centrality(
g::AbstractGraph, vs=vertices(g)
)::Vector{Int64}
n_v = nv(g)
k = length(vs)
isdir = is_directed(g)

# Parallel reduction
stress = @distributed (+) for s in vs
temp_stress = zeros(Int64, n_v)
if degree(g, s) > 0 # this might be 1?
state = Graphs.dijkstra_shortest_paths(g, s; allpaths=true, trackvertices=true)
Graphs._stress_accumulate_basic!(temp_stress, state, g, s)
end
temp_stress
end
return stress
end

# generate_reduce
function Graphs.Parallel.distr_generate_reduce(
g::AbstractGraph{T}, gen_func::Function, comp::Comp, reps::Integer
) where {T<:Integer,Comp}
# Type assert required for type stability
min_set::Vector{T} = @distributed ((x, y) -> comp(x, y) ? x : y) for _ in 1:reps
gen_func(g)
end
return min_set
end

# eccentricity
function Graphs.Parallel.distr_eccentricity(
g::AbstractGraph, vs=vertices(g), distmx::AbstractMatrix{T}=weights(g)
) where {T<:Number}
vlen = length(vs)
eccs = SharedVector{T}(vlen)
@sync @distributed for i in 1:vlen
d′ = Graphs.dijkstra_shortest_paths(g, vs[i], distmx)
eccs[i] = maximum(d′.dists)
end
d = sdata(eccs)
maximum(d) == typemax(T) && @warn("Infinite path length detected")
return d
end

# dijkstra shortest paths
function Graphs.Parallel.distr_dijkstra_shortest_paths(
g::AbstractGraph{U}, sources=vertices(g), distmx::AbstractMatrix{T}=weights(g)
) where {T<:Number} where {U}
n_v = nv(g)
r_v = length(sources)

# TODO: remove `Int` once julialang/#23029 / #23032 are resolved
dists = SharedMatrix{T}(Int(r_v), Int(n_v))
parents = SharedMatrix{U}(Int(r_v), Int(n_v))

@sync @distributed for i in 1:r_v
state = Graphs.dijkstra_shortest_paths(g, sources[i], distmx)
dists[i, :] = state.dists
parents[i, :] = state.parents
end

result = Graphs.Parallel.MultipleDijkstraState(sdata(dists), sdata(parents))
return result
end

# random greedy color
function Graphs.Parallel.distr_random_greedy_color(
g::AbstractGraph{T}, reps::Integer
) where {T<:Integer}
best = @distributed (Graphs.best_color) for i in 1:reps
seq = shuffle(vertices(g))
Graphs.perm_greedy_color(g, seq)
end

return convert(Graphs.Coloring{T}, best)
end

end
4 changes: 4 additions & 0 deletions src/Graphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -560,5 +560,9 @@ include("Experimental/Experimental.jl")
include("Parallel/Parallel.jl")
include("Test/Test.jl")

if !isdefined(Base, :get_extension)
include("../ext/GraphsSharedArraysExt.jl")
end

using .LinAlg
end # module
2 changes: 0 additions & 2 deletions src/Parallel/Parallel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ module Parallel

using Graphs
using Graphs: sample, AbstractPathState, JohnsonState, BellmanFordState, FloydWarshallState
using Distributed: @distributed
using Base.Threads: @threads, nthreads, Atomic, atomic_add!, atomic_cas!
using SharedArrays: SharedMatrix, SharedVector, sdata
using ArnoldiMethod: LM, SR, LR, partialschur, partialeigen
using Random: AbstractRNG, shuffle
import SparseArrays: sparse
Expand Down
39 changes: 6 additions & 33 deletions src/Parallel/centrality/betweenness.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
distmx::AbstractMatrix=weights(g);
normalize=true,
endpoints=false,
parallel=:distributed,
parallel=:threads,
)
return if parallel == :distributed
distr_betweenness_centrality(
Expand All @@ -23,7 +23,7 @@
distmx::AbstractMatrix=weights(g);
normalize=true,
endpoints=false,
parallel=:distributed,
parallel=:threads,
rng::Union{Nothing,AbstractRNG}=nothing,
seed::Union{Nothing,Integer}=nothing,
)
Expand All @@ -39,37 +39,10 @@
end
end

function distr_betweenness_centrality(
g::AbstractGraph,
vs=vertices(g),
distmx::AbstractMatrix=weights(g);
normalize=true,
endpoints=false,
)::Vector{Float64}
n_v = nv(g)
k = length(vs)
isdir = is_directed(g)

# Parallel reduction

betweenness = @distributed (+) for s in vs
temp_betweenness = zeros(n_v)
if degree(g, s) > 0 # this might be 1?
state = Graphs.dijkstra_shortest_paths(
g, s, distmx; allpaths=true, trackvertices=true
)
if endpoints
Graphs._accumulate_endpoints!(temp_betweenness, state, g, s)
else
Graphs._accumulate_basic!(temp_betweenness, state, g, s)
end
end
temp_betweenness
end

Graphs._rescale!(betweenness, n_v, normalize, isdir, k)

return betweenness
function distr_betweenness_centrality(args...; kwargs...)
return error(

Check warning on line 43 in src/Parallel/centrality/betweenness.jl

View check run for this annotation

Codecov / codecov/patch

src/Parallel/centrality/betweenness.jl#L42-L43

Added lines #L42 - L43 were not covered by tests
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
)
end

function distr_betweenness_centrality(
Expand Down
36 changes: 5 additions & 31 deletions src/Parallel/centrality/closeness.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
function closeness_centrality(
g::AbstractGraph,
distmx::AbstractMatrix=weights(g);
normalize=true,
parallel=:distributed,
g::AbstractGraph, distmx::AbstractMatrix=weights(g); normalize=true, parallel=:threads
)
return if parallel == :distributed
distr_closeness_centrality(g, distmx; normalize=normalize)
Expand All @@ -11,33 +8,10 @@
end
end

function distr_closeness_centrality(
g::AbstractGraph, distmx::AbstractMatrix=weights(g); normalize=true
)::Vector{Float64}
n_v = Int(nv(g))
closeness = SharedVector{Float64}(n_v)
fill!(closeness, 0.0)

@sync @distributed for u in vertices(g)
if degree(g, u) == 0 # no need to do Dijkstra here
closeness[u] = 0.0
else
d = Graphs.dijkstra_shortest_paths(g, u, distmx).dists
δ = filter(x -> x != typemax(x), d)
σ = sum(δ)
l = length(δ) - 1
if σ > 0
closeness[u] = l / σ
if normalize
n = l * 1.0 / (n_v - 1)
closeness[u] *= n
end
else
closeness[u] = 0.0
end
end
end
return sdata(closeness)
function distr_closeness_centrality(args...; kwargs...)
return error(

Check warning on line 12 in src/Parallel/centrality/closeness.jl

View check run for this annotation

Codecov / codecov/patch

src/Parallel/centrality/closeness.jl#L11-L12

Added lines #L11 - L12 were not covered by tests
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
)
end

function threaded_closeness_centrality(
Expand Down
22 changes: 5 additions & 17 deletions src/Parallel/centrality/radiality.jl
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@
function radiality_centrality(g::AbstractGraph; parallel=:distributed)
function radiality_centrality(g::AbstractGraph; parallel=:threads)
return if parallel == :distributed
distr_radiality_centrality(g)
else
threaded_radiality_centrality(g)
end
end

function distr_radiality_centrality(g::AbstractGraph)::Vector{Float64}
n_v = nv(g)
vs = vertices(g)
n = ne(g)
meandists = SharedVector{Float64}(Int(n_v))
maxdists = SharedVector{Float64}(Int(n_v))

@sync @distributed for i in 1:n_v
d = Graphs.dijkstra_shortest_paths(g, vs[i])
maxdists[i] = maximum(d.dists)
meandists[i] = sum(d.dists) / (n_v - 1)
nothing
end
dmtr = maximum(maxdists)
radialities = collect(meandists)
return ((dmtr + 1) .- radialities) ./ dmtr
function distr_radiality_centrality(args...; kwargs...)
return error(

Check warning on line 10 in src/Parallel/centrality/radiality.jl

View check run for this annotation

Codecov / codecov/patch

src/Parallel/centrality/radiality.jl#L9-L10

Added lines #L9 - L10 were not covered by tests
"`parallel = :distributed` requested, but SharedArrays or Distributed is not loaded"
)
end

function threaded_radiality_centrality(g::AbstractGraph)::Vector{Float64}
Expand Down
Loading
Loading