Hey there. Maybe this is obvious, but I'm having trouble with dicts and the time it takes.
For example, I have a function that takes a graph and vertex positions and calculates the line segments for edges. This takes only ~15μs. But for some reason, the line the assigns this to a dictionary takes like ~50ms, the line is edges_to_segments::Dict{Tuple{Graphs.SimpleGraphs.SimpleEdge{Int64}, Int64}, GeometryBasics.Line{2, Float32}} = get_edges_to_segments(G, positions)
Is there no way to use a dict and have this be fast? I tried giving a size hint and I don't think it did anything.
It's hard to even speculate without any information of what get_edges_to_segments
actually does or how it is implemented.
Here is a minimum running example that is set up to demonstrates it.
using LinearAlgebra
using Graphs
using TimerOutputs
using GeometryBasics
using NetworkLayout
const to = TimerOutput()
function testing_generate_graph()
n = rand(45:60)
max_edges = n * (n - 1) ÷ 2
e = min(3 * n - 4, max_edges)
graph = SimpleGraph(n, e)
#graph = SimpleDiGraph(n, e)
return graph
end
function testing_generate_layout(graph::AbstractGraph)
layout = SFDP(Ptype = Float32, tol = 0.01, C = 0.2, K = 1)
#layout = Spring()
positions = layout(graph)
return positions
end
@timeit to function get_edges_to_segments(
graph::AbstractGraph,
positions::Vector{GeometryBasics.Point{2,Float32}},
)
#=
edges_to_segments = Dict(
(e, i) => Segment(
Meshes.Point(positions[src(e)][1], positions[src(e)][2]),
Meshes.Point(positions[dst(e)][1], positions[dst(e)][2]),
) for (i, e) in enumerate(edges(graph))
) =#
edges_to_segments::Dict{Tuple{Graphs.SimpleGraphs.SimpleEdge{Int64}, Int64}, GeometryBasics.Line{2, Float32}} = Dict(
(e, i) => GeometryBasics.Line(
positions[src(e)],
positions[dst(e)],
) for (i, e) in enumerate(edges(graph))
)
return edges_to_segments
end
G = testing_generate_graph()
vertpositions = testing_generate_layout(G)
@timeit to "section1" begin
result = get_edges_to_segments(G, vertpositions)
end
to_flatten = TimerOutputs.flatten(to)
show(to_flatten; compact = true, allocations = false)
What if you define
edges_to_segments::Dict{Tuple{Graphs.SimpleGraphs.SimpleEdge{Int64}, Int64}, GeometryBasics.Line{2, Float32}} = Dict{Tuple{Graphs.SimpleGraphs.SimpleEdge{Int64}, Int64}, GeometryBasics.Line{2, Float32}}(
(e, i) => GeometryBasics.Line(
positions[src(e)],
positions[dst(e)],
) for (i, e) in enumerate(edges(graph))
)
?
That is, create your initial dict with the desired type, rather than with ??? type and converting it to the desired type.
I think this was solved on Discourse
Lilith Hafner has marked this topic as resolved.
Last updated: Nov 06 2024 at 04:40 UTC