I have the following function that is going to be called hundreds of thousands of times, and right now it’s running way too slow.
function sample_σ!(metrop::LJ_metrop,data::DataSet,LJ::LJ,LJ_next::LJ,std)
for j = 1:LJ.order, k = j:LJ.order
#println(LJ.σ,metrop.σ_candSigs)
cand = rand(metrop.proposal(LJ.σ[j,k],metrop.σ_candSigs[j,k]))
if cand < 0.05
continue
end
LJ_next.σ[j,k] = cand # Set sigma equal to the candidate draw
# Evaluate the posterior at the candidate draw.
numerator = metrop.logpost(data,LJ_next,std) + log(pdf(metrop.proposal(cand,metrop.σ_candSigs[j,k]),LJ.σ[j,k]))
LJ_next.σ[j,k] = LJ.σ[j,k] # Set sigma back to the previous draw.
# Evaluate the posterior again.
denominator =metrop.logpost(data,LJ_next,std) + log(pdf(metrop.proposal(LJ.σ[j,k],metrop.σ_candSigs[j,k]),cand))
r = numerator - denominator
unif = log(rand(Uniform(0,1))) # Draw from a uniform.
if r >= 0 || ((r < 0) & (unif < r)) # Accept?
LJ_next.σ[j,k] = cand
# metrop.params_draws[i,j,k,l] = cand # Yes!
metrop.σ_accept[j,k] += 1/metrop.nDraws
end
end
end
LJ.order = 2
so the nested loop inside the function is only running 3 iterations.
Here are the relevant user-defined types:
struct LJ_metrop
nDraws:: Int64
nBurnIn:: Int64
# Acceptance rates for all of the parameters
ϵ_accept:: UpperTriangular{Float64, Matrix{Float64}}
σ_accept:: UpperTriangular{Float64, Matrix{Float64}}
std_accept:: Vector{Float64}
# Prior distributions
ϵ_Priors:: Array{Distribution,2}#Vector{Distribution}
σ_Priors:: Array{Distribution,2}
std_Prior:: Distribution
# Sigmas on proposal distributions
ϵ_candSigs:: UpperTriangular{Float64, Matrix{Float64}}
σ_candSigs:: UpperTriangular{Float64, Matrix{Float64}}
std_candSig:: Float64
# Initial guess
std:: Float64
# Proposal distribution
proposal:: Function
# Posterior
logpost:: Function
end
struct LJ <: energyModel
order:: Int
# params:: Array{Float64,3}
cutoff:: Float64
# Replace params above.
σ:: UpperTriangular{Float64, Matrix{Float64}}
ϵ:: UpperTriangular{Float64, Matrix{Float64}}
end
mutable struct Crystal
title::String
latpar::Float64
lVecs:: Matrix{Float64}
nType:: Vector{Int64} #Number of each type of atom
aType:: Vector{Int64} # Integers representing the type for each basis atom
nAtoms::Int64 # Total number of atoms in the unit cell
coordSys::Vector{String} # 'D' for Direct or 'C' for cartesian
atomicBasis:: Vector{Vector{Vector{Float64}}} # List of all the atomic basis vector separated by type
species:: Vector{String} # Species of the atoms
energyFP:: Float64 # First principles energy
modelEnergy:: Float64 # Model energy
order::Int64 # binary, ternary, etc.
r6::UpperTriangular{Float64, Matrix{Float64}}
r12::UpperTriangular{Float64, Matrix{Float64}}
end
and here are the two functions that are being called:
proposal(μ,σ) = Gamma(μ^2/σ^2,σ^2/μ)
logPost(data,model,σ) = MatSim.logNormal(data,model,σ) + sum(logpdf.(σ_Priors,model.σ)) + sum(logpdf.(ϵ_Priors,model.ϵ)) + logpdf(std_Prior,σ)
I’m not asking you to spend a lot of time optimizing my code. Just wondering if anyone can see any glaring problems that would help out. Also, just trying to learn the general tips/tricks for optimizing julia. I still don’t have good intuition/ habits for optimizing in julia so trying to build that.
Right now when I call this function 50,000 times, it’s allocating a little over 3.0 G and taking over a minute to execute. Feels like I could do better. Thanks in advance