Concrete Example 0805: how to prevent using global variable in the module?

I agree with leandromartinez98-san.

As I already mentioned, in my personal opinion, it is safer to avoid using constants to fix the types, especially when using Julia for scientific purposes.

For example, if you fix the type to Float64, you will not be able to use automatic differentiation. (cf. Avoid writing overly-specific types)

See also

In this case, there is no need to share something global with multiple functions without going through function arguments.

I have tried minimal changes.

Code

module O

export musigma

struct Mean_covar{T}
    mu::Vector{T}
    sigma::Matrix{T}
    w::Array{T,0}
end

function mean_covar_init(kmix, dim_p, 
        weight::AbstractVector{T},
        sigma::AbstractArray{T,3},
        mu::AbstractMatrix{T}) where T
    @assert size(weight) == (kmix,)
    @assert size(sigma) == (kmix, dim_p, dim_p)
    @assert size(mu) == (kmix, dim_p)
    musigma = Vector{Mean_covar{T}}(undef, kmix)
    for k in 1:kmix
        musigma[k] = Mean_covar(zeros(T, dim_p), zeros(T, dim_p, dim_p), fill(zero(T)))
        musigma[k].mu[1,1] = mu[k,1]
        musigma[k].mu[2,1] = mu[k,2]
        musigma[k].sigma[1,1] = sigma[k,1,1]
        musigma[k].sigma[2,2] = sigma[k,2,2]
        musigma[k].w[] = weight[k]
    end
    musigma
end

end
kmix = 5
dim_p = 3
weight = rand(kmix)
sigma = rand(kmix, dim_p, dim_p)
mu = rand(kmix, dim_p)

musigma64 = O.mean_covar_init(kmix, dim_p, weight, sigma, mu)
@show typeof(musigma64) size(musigma64)
@show musigma64[1].mu musigma64[1].sigma musigma64[1].w;

Result

typeof(musigma64) = Vector{Main.O.Mean_covar{Float64}}
size(musigma64) = (5,)
(musigma64[1]).mu = [0.25133930343144617, 0.6524185771129412, 0.0]
(musigma64[1]).sigma = [0.6391609541493193 0.0 0.0; 0.0 0.8803430485817509 0.0; 0.0 0.0 0.0]
(musigma64[1]).w = fill(0.6189491252747268)```

You can also use Float32 type.

weight32 = rand(Float32, kmix)
sigma32 = rand(Float32, kmix, dim_p, dim_p)
mu32 = rand(Float32, kmix, dim_p)

musigma32 = O.mean_covar_init(kmix, dim_p, weight32, sigma32, mu32)
@show typeof(musigma32) size(musigma32)
@show musigma32[1].mu musigma32[1].sigma musigma32[1].w;
typeof(musigma32) = Vector{Main.O.Mean_covar{Float32}}
size(musigma32) = (5,)
(musigma32[1]).mu = Float32[0.27483153, 0.21964681, 0.0]
(musigma32[1]).sigma = Float32[0.16200805 0.0 0.0; 0.0 0.9208745 0.0; 0.0 0.0 0.0]
(musigma32[1]).w = fill(0.2774073f0)

If there is a possibility of using GPU, it is important to be able to use Float32 as well. However, in the above example, the type of the fields of Mean_covar type are fixed to Array’s, the design of which is insufficient to use GPU.

Changes

  • mutable struct Mean_covar → immutable struct Mean_covar{T} (fields are all mutable)
  • type of muVector{T} = Array{T,1}
  • type of weightMatrix{T} = Array{T,2}
  • type of wArray{T,0}, 0-dimensional array (this is mutable)
  • delete global const musigma in the module
  • mean_covar_init constructs and returns musigma

Point: The module O above does not contain any concrete type names like Float64.

In general, you should use the most general applicable abstract types for arguments, and when in doubt, omit the argument types.

2 Likes