Hello all.
I’ve started playing around with Julia and am trying to write a molecular dynamics program.
That involves dealing with a lot of short arrays. I decided to use the following structure for coordinates:
struct Views3D{T}
vec::Vector{<:SubArray{T,1,Vector{T}}}
data::Vector{T}
end
Here, data
is a length-3N vector which holds the related vectors for N atoms, and vec[i]
is data[3(i-1)+1:3i]
, i.e. the vector for i
th particle.
The atom data are arranged as follows:
struct InnerAtoms
num::Base.RefValue{Int} # number of particles
r::Views3D{Float64}
v::Views3D{Float64}
f::Views3D{Float64}
end
For some reason, that leads to memory allocation whenever the atom coordinates are processed. E.g., the following code puts coordinates inside the box if a particle got out:
@inbounds for iatom in 1:natoms
rvec = box.atoms.r.vec[iatom]
for j = 1:3
if rvec[j] < boxlo[j]
rvec[j] += boxdim[j]
elseif rvec[j] >= boxhi[j]
rvec[j] -= boxdim[j]
end
end
end
That code, however, allocates a lot. With @code_warntype
, I get the following transcript:
│ %144 = (Base.getfield)(box, :atoms)::Main.JlMol.Atoms.InnerAtoms
│ %145 = (Base.getfield)(%144, :r)::Main.JlMol.Atoms.Views3D{Float64}
│ %146 = (Base.getfield)(%145, :vec)::Array{#s36,1} where #s36<:(SubArray{Float64,1,Array{Float64,1},I,L} where L where I)
│ %147 = (Base.getindex)(%146, %142)::SubArray{Float64,1,Array{Float64,1},I,L} where L where I
└──── goto #50 if not true
41 ┄─ %149 = φ (#40 => 1, #49 => %173)::Int64
│ %150 = φ (#40 => 1, #49 => %174)::Int64
│ %151 = (Base.getindex)(%147, %149)::Any
So, the compiler knows that rvec
is a subarray of Float64
type but cannot infer that rvec[i]
is a Float64
?
Is it possible to change the structure definition to avoid those memory allocations?