I’m running into performance bottlenecks running a diffusion model I put into LightGraphs.jl (code here and was wondering if anyone might have any suggestions. (p.s. I’m not entirely clear if this belong here or stack overflow – please let me know if I’m in the wrong place!). In my research application, I’m running this on networks of about 10_000_000 nodes thousands of times, so performance really matters.
Profiling the code, I find 70% of run time is generally in Line 57:
union!(new_infections, randsubseq(outn, local_p))
Which may mean there’s nothing to improve on. But I’m not yet fully comfortable working with @code_warntype
, so it strikes me that maybe I’m missing something? It’s relatively clean, but is popping up some read. I think think any of that red matters, but like I said, I’m new to this, and have spent a week trying to find improvements, so would love to know if I just need to parallelize more, or if I’m missing something.
You can get the relevant @code_warntype
with:
Pkg.add("LightGraphs")
using LightGraphs
g = erdos_renyi(1_000, 5_000, seed=42)
@code_warntype diffusion(g, 0.6, 100, normalize=true, watch=collect(300:700), initial_infections=[400])
Or read:
julia> @code_warntype diffusion(g, 0.6, 100, normalize=true, watch=collect(300:700),
initial_infections=[400])
Variables:
#unused#::LightGraphs.#kw##diffusion
#temp#@_2::Array{Any,1}
::LightGraphs.#diffusion
g::LightGraphs.SimpleGraphs.SimpleGraph{Int64}
p::Float64
n::Int64
#temp#@_7::Int64
#temp#@_8::Int64
#temp#@_9::Any
#temp#@_10::Int64
watch::AbstractArray{T,1} where T
initial_infections::AbstractArray{T,1} where T
normalize::Bool
#temp#@_14::Bool
#temp#@_15::Bool
Body:
begin
NewvarNode(:(watch::AbstractArray{T,1} where T))
NewvarNode(:(initial_infections::AbstractArray{T,1} where T))
#temp#@_14::Bool = true
#temp#@_15::Bool = true
normalize::Bool = false
SSAValue(2) = (Base.arraylen)(#temp#@_2::Array{Any,1})::Int64
SSAValue(3) = (Base.select_value)((Base.sle_int)(0, 1)::Bool, (Base.ashr_int)(SSAValue(2), (Base.bitcast)(UInt64, 1))::Int64, (Base.shl_int)(SSAValue(2), (Base.bitcast)(UInt64, (Base.neg_int)(1)::Int64))::Int64)::Int64
SSAValue(7) = (Base.select_value)((Base.sle_int)(1, SSAValue(3))::Bool, SSAValue(3), (Base.sub_int)(1, 1)::Int64)::Int64
#temp#@_10::Int64 = 1
10:
unless (Base.not_int)((#temp#@_10::Int64 === (Base.add_int)(SSAValue(7), 1)::Int64)::Bool)::Bool goto 39
SSAValue(8) = #temp#@_10::Int64
SSAValue(9) = (Base.add_int)(#temp#@_10::Int64, 1)::Int64
#temp#@_7::Int64 = SSAValue(8)
#temp#@_10::Int64 = SSAValue(9)
#temp#@_8::Int64 = (Base.sub_int)((Base.mul_int)(#temp#@_7::Int64, 2)::Int64, 1)::Int64
#temp#@_9::Any = (Core.arrayref)(#temp#@_2::Array{Any,1}, #temp#@_8::Int64)::Any
unless (#temp#@_9::Any === :normalize)::Bool goto 21
normalize::Bool = (Core.typeassert)((Core.arrayref)(#temp#@_2::Array{Any,1}, (Base.add_int)(#temp#@_8::Int64, 1)::Int64)::Any, LightGraphs.Bool)::Bool
goto 37
21:
unless (#temp#@_9::Any === :initial_infections)::Bool goto 26
initial_infections::AbstractArray{T,1} where T = (Core.typeassert)((Core.arrayref)(#temp#@_2::Array{Any,1}, (Base.add_int)(#temp#@_8::Int64, 1)::Int64)::Any, LightGraphs.AbstractVector)::AbstractArray{T,1} where T
#temp#@_15::Bool = false
goto 37
26:
unless (#temp#@_9::Any === :watch)::Bool goto 31
watch::AbstractArray{T,1} where T = (Core.typeassert)((Core.arrayref)(#temp#@_2::Array{Any,1}, (Base.add_int)(#temp#@_8::Int64, 1)::Int64)::Any, LightGraphs.AbstractVector)::AbstractArray{T,1} where T
#temp#@_14::Bool = false
goto 37
31:
SSAValue(10) = ::LightGraphs.#diffusion
SSAValue(11) = g::LightGraphs.SimpleGraphs.SimpleGraph{Int64}
SSAValue(12) = p::Float64
SSAValue(13) = n::Int64
(Base.throw)($(Expr(:new, :(Base.MethodError), :((Core.getfield)((Core.getfield)((Core.getfield)(LightGraphs.#diffusion, :name)::TypeName, :mt), :kwsorter)), :((Core.tuple)(#temp#@_2, SSAValue(10), SSAValue(11), SSAValue(12), SSAValue(13))::Tuple{Array{Any,1},LightGraphs.#diffusion,LightGraphs.SimpleGraphs.SimpleGraph{Int64},Float64,Int64}), 0xffffffffffffffff)))::Union{}
37:
goto 10
39:
unless #temp#@_14::Bool goto 42
watch::AbstractArray{T,1} where T = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Int64,1}, svec(Any, Int64), Array{Int64,1}, 0, 0, 0))
42:
unless #temp#@_15::Bool goto 50
$(Expr(:inbounds, false))
# meta: location /Users/Nick/.julia/v0.6/LightGraphs/src/graphtypes/simplegraphs/SimpleGraphs.jl vertices 44
SSAValue(6) = (Base.arraylen)((Core.getfield)(g::LightGraphs.SimpleGraphs.SimpleGraph{Int64}, :fadjlist)::Array{Array{Int64,1},1})::Int64
# meta: pop location
$(Expr(:inbounds, :pop))
initial_infections::AbstractArray{T,1} where T = $(Expr(:invoke, MethodInstance for (::LightGraphs.#kw##sample!)(::Array{Any,1}, ::LightGraphs.#sample!, ::MersenneTwister, ::Array{Int64,1}, ::Int64), :($(QuoteNode(LightGraphs.#sample!))), :($(Expr(:invoke, MethodInstance for vector_any(::Any, ::Vararg{Any,N} where N), :(Base.vector_any), :(:exclude), ()))), :(LightGraphs.sample!), :($(Expr(:invoke, MethodInstance for getRNG(::Int64), :(LightGraphs.getRNG), -1))), :($(Expr(:invoke, MethodInstance for vcat(::UnitRange{Int64}), :(Base.vcat), :($(Expr(:new, UnitRange{Int64}, 1, :((Base.select_value)((Base.sle_int)(1, SSAValue(6))::Bool, SSAValue(6), (Base.sub_int)(1, 1)::Int64)::Int64))))))), 1))
50:
return (LightGraphs.#diffusion#57)(watch::AbstractArray{T,1} where T, initial_infections::AbstractArray{T,1} where T, normalize::Bool, ::LightGraphs.#diffusion, g::LightGraphs.SimpleGraphs.SimpleGraph{Int64}, p::Float64, n::Int64)::Array{Array{Int64,1},1}
end::Array{Array{Int64,1},1}