I’m making a Monte Carlo simulation program. The object my simulation is working on is a graph, which I represent by struct
mutable struct IsingGraph
state::Vector{Int8}
adj::Vector{Vector{Int32}}
...
eprops::Dict{Edge,Dict{Symbol,Any}}
end
The field state holds a -1 or 1, and the field adj is a vector, which maps every index of the state vector to a few other indices. The dict props is used to just hold weights.
I have a function which gets the energy for an index. I’m trying to include optional weights, and was trying to make a new function to be able to do this. These are the two functions:
function getH(g,idx)
Estate = 0
for jdx in g.adj[idx]
@inbounds Estate += -g.state[idx]*g.state[jdx]
end
return Estate
end
function getH(g::IsingGraph, idx::Integer ; weighted::Bool = false)
@inbounds conns = g.adj[idx]
E = 0
@inbounds state = g.state[idx]
if !weighted
for conn in conns
@inbounds E += -state*g.state[conn]
end
else
for conn in conns
E += -g.eprops[idx=>conn][:weight] * state*g.state[conn]
end
end
return E
end
If I execute either of these with weighted = false
for getH, I get about 3.6ns of execution time. However, my simulation is ran by the following function
function updateMonteCarlo!(g::IsingGraph, T)
beta = T>0 ? 1/T : Inf
idx = rand(ising_it(g))
Estate = getH(g,idx) # /getE(g, idx)
if (Estate >= 0 || rand() < exp(2*beta*Estate))
@inbounds g.state[idx] *= -1
end
end
Here, depending on if I use getH or getE, the execution time of updateMonteCarlo! will be around 150ns, or 50ns respectively. I found out that if I remove the [:weight] part from the line (causing the line to not make sense, which doesn’t matter for execution since it is not executed), the execution time is about 50-60ns again.
Why is getH so much slower in this case? I’m assuming the compiler is failing to make some optimisation somewhere. Does it have anything to do with the fact that the type of E can potentially change, because the return type of the dict is any?