I have some code that I feel should run faster (see below). So I ran it with @profile
and looked at the results with ProfileView.view()
and as expected a lot of red showed up (i.e. runtime method lookup), the correspinding lines are commented in the code below. But when I run @code_warntype
on the same function I get no red and it seems, all the code is nice and type stable. As far as I see ΔE
is type stable and returns exactly what the annotation says, so why does it still get flagged as needing runtime method lookup?
And how do correctly annotate / write the code, such that no runtime method lookup is needed.
up = CartesianIndex(0, 1)
right = CartesianIndex(1, 0)
down = CartesianIndex(0, -1)
left = CartesianIndex(-1, 0)
"Calculate the total energy of 2D Ising model with coupling J and field H"
function energy(lattice, J, H)::Float64
energy = 0.0
for i in eachindex(lattice)
energy -= H*lattice[i]*(1. + J * lattice[i+up] + J * lattice[i+right])
end
return energy
end
"Calculate the total magnetization of the lattice"
magnetization(lattice)::Int = sum(lattice)
"The energy difference when flipping the spin on `site`"
@inline @propagate_inbounds function ΔE(lattice, site, J, H)::Float64
out = ( 2H*lattice[site] # runtime method lookup here
+ 2J*lattice[site]*(lattice[site+up] + lattice[site+down]
+ lattice[site+left] + lattice[site+right]))
out
end
"Make a Markov Chain Monte Carlo Step on the lattice"
function MCMCStep!(lattice,
J,
H)::Tuple{Float64,Int}
site = rand(CartesianIndices(lattice))
@inbounds δE = ΔE(lattice, site, J, H) # runtime method lookup here
if δE < 0.0
@inbounds δM = -lattice[site]
@inbounds lattice[site] = δM
elseif exp(-δE) > rand()
@inbounds δM = -lattice[site]
@inbounds lattice[site] = δM # runtime method lookup
else
δE = 0.0::Float64
δM = 0::Int
end
return (δE, 2*δM) #this line gets flagged as slow
end
function MCMCRun(lattice, steps, J, H) where {N}
E0 = energy(lattice, J, H)
M0 = magnetization(lattice)
E = E0
M = M0
energies = Array{Float64}(undef, steps)
magnetizations = Array{Int64}(undef, steps)
for i in 1:steps
for j in 1:length(lattice)
δE, δM = MCMCStep!(lattice, J, H) # this is where all the time is spent with a runtime method lookup
E += δE
M += δM
end
energies[i] = E
magnetizations[i] = M
end
E1 = energy(lattice, J, H)
M1 = magnetization(lattice)
return energies, magnetizations
end