Let me refactor a bit
module Step
using LinearAlgebra
using DelimitedFiles
using Printf
include("Ran.jl")
using .Ran
include("Constants.jl")
using .Constants
#include("Mixture.jl")
#using .Mixture
include("Analysis.jl")
using .Analysis
export step_init,prep,steps,read_Yji,push_Yji,get_musigma,get_musigma_maxLL,musigma,mean_covar_init
mutable struct MeanCovar # Mean_covar does not follow Julian naming conventions
mu::Array{Float64,2}
sigma::Array{Float64,2}
w::Float64
end
mutable struct GlobalStateIDontNeed
musigma::Vector{MeanCovar}
imode::Int # is global, make it a Ref to lock the type
itermax::Int
msample::Int
mgauss::Int
mi::Int
nsub::Int
dim_p::Int
kmix::Int
sig::Float64
sig_inv::Float64
SigV::Float64
mu1::Float64
sig1::Float64
mu2::Float64
sig2::Float64
muV::Float64
w1::Float64
w2::Float64
mitot::Int
mgauss_tot::Int
mgauss_max::Int
mgauss_min::Int
iter::Int
sigma_factor::Float64
D::Float64
normpdf_factor_pYq_i::Float64
log_normpdf_factor_pYq_i::Float64
h_diag::Array{Float64,3}
ymh::Array{Float64,3}
thetas::Array{Float64,3}
muk_iter::Matrix{Float64}
sigk_iter::Matrix{Float64}
muV_iter::Matrix{Float64}
sigV_iter::Matrix{Float64}
wk_iter::Matrix{Float64}
mukerror_iter::Matrix{Float64}
sigkerror_iter::Matrix{Float64}
ar_gik_k::Matrix{Float64}
muVerror_iter::Matrix{Float64}
sigVerror_iter::Matrix{Float64}
log_pYq_km::Matrix{Float64}
nik::Matrix{Float64}
nik_sig::Matrix{Float64}
wknik::Matrix{Float64}
wknik_sig::Matrix{Float64}
tauik::Matrix{Float64}
Yji::Matrix{Float64}
mgauss_ik::Matrix{Int}
isub_Metroplis_gik_all::Matrix{Int}
LL_iter::Vector{Float64}
sigma_iter::Vector{Float64}
ar_gik::Vector{Float64}
sigmaerror_iter::Vector{Float64}
norm::Vector{Float64}
norm_sig::Vector{Float64}
normerr::Vector{Float64}
log_norm::Vector{Float64}
wnow::Vector{Float64}
log_wnow::Vector{Float64}
t::Vector{Float64}
fmt_k_iter::Any
fmt_float_iter::Any
fmt_float_err_iter::Any
end
function step_init(mean_cov_in::Vector{MeanCovar},imodein::Int64,itermaxin::Int64,min::Int64,mgaussin::Int64,miin::Int64,nsubin::Int64,pin::Int64,kmixin::Int64
,mu1in::Float64,sig1in::Float64,mu2in::Float64,sig2in::Float64
,muVin::Float64,sigVin::Float64
,w1in::Float64,w2in::Float64,sigin::Float64
,Din::Float64,tin::Array{Float64,1})
@assert length(tin) == miin
state = GlobalStateIDontNeed(
mean_cov_in,
imodein,
itermaxin,
miin,
nsubin,
...
)
... # proceed with initialization
return state
end
const GLOBAL_STATE_TO_GET_RID_OF = step_init(#=some arguments=#)
voilà, now there’s only one global constant.
Of course, now you need to type
GLOBAL_STATE_TO_GET_RID_OF.imode = ...
instead of
imode[] = ...
but that makes the code much easier to understand for a person who did not write it.
Now, global Ref
s are not zero-cost. You get an extra indirection each time you access the data.
Having MeanCovar
as a mutable struct also has costs.
You see, Julia is a pretty bad Fortran, but is a good Julia language. So, you absolutely should not write Fortran in Julia and must not base your conclusions about overall Julia performance on the performance of Fortran code written in Julia. If you’d like to write Fortran, it’s best to use a Fortran compiler to build your applications because doing it with the Julia compiler won’t be any more performant or easier to maintain and extend.
And, well, I have not seen anything “modern” in your Fortran code posted earlier, so your references to “modern Fortran” are way off IMO. That the code uses =
instead of .eq.
etc. does not make it modern. Getting rid of programming antipatterns stemming from 60’s when computers had 1000 words of memory does. Even then, avoiding globals and using immutable state if possible are not new patterns either, they are advocated in “Structure and Interpretation of Computer Programs”, a 1985 book!
The answer to the topic title is, IMO:
- for the same algorithm, Julia is on par with Fortran, modern or not
- for the same Fortran code, Julia is likely to be several times slower because it has not been designed to compile Fortran code efficiently
- for the same Julia code, Julia is likely to be orders of magnitude faster than Fortran because may spend years to re-implement in Fortran what can be done in days in Julia