Hello Everyone,
I am fairly new to Julia, so sorry if the problem I would like to ask about may seem a bit general.
I have actually written a plasma simulation code which is unfortunately too much detailed and consisting of too many lines to be put here in its entirety. But just to give some context, it’s basically a code to push around some large number of “particles” (typically around 5e5 to 1e6) and to perform some checks and actions on them. Fast Forward to the problem I observe, the code starts off quite fast but as the number of iterations increases, it starts to getting slower and slower. I am including a figure below to show the code runtime variation over time. This figure is obtained by running the code for 20,000 iterations and for a particle count of 30,000. For the timing, I have used @time
for the entire loop (so in Global Scope which should still give an indication of runtime).
As just a quick hint, the increase in runtime is somewhat expected as the number of particles increases through iterations and some functions are being called more times. However, the expected time rise is about 2 percent whereas here the increase is about a factor of 3.5.
Now to explain a little bit the code structure, to store each particle information, I have defined a custom type called Particle as a mutable structure. It contains 4 arrays of type MVector{3, Float64}
and one parameter of type Float64
. All particles defined as above are then stored within another array which is itself included in another immutable structure as a data wrapper. The code snippet for these structures is below:
mutable struct Particle
pos::MVector{3,Float64}
vel::MVector{3,Float64}
cellIndex::MVector{3,Int64}
posInCell::MVector{3,Float64}
mpwt::Float64
end
struct Species
name::String
particles::Array{Particle,1}
charge::Float64
mass::Float64
van_der_waals_radius::Float64
end
Within the code main loop, I need to add particles to the array containing them and also delete some of them that exceed simulation domain boundaries. To do this, I have been using push!
to add to the particles
array and deleteat!
to remove data from it as below:
push!(species.particles, part)
deleteat!(species.particles, i)
where i
is the index of element to be deleted.
After observing performance degradation, I did some profiling and it seemed like the functions in which push!
and deleteat!
are called could be the reason. I was specifically concerned about shifts in memory whenever data are being added or removed from the particles
array. As a result, I tried replacing deleteat!
with the following, which effectively tries to replace the item to be deleted with an element from the end of the array and then delete that last element.
species.particles[i] = species.particles[end]
deleteat!(species.particles, length(species.particles))
This approach did not work and even reduced further the performance. Then I thought about push!
and instead tried preallocating the particles arrays using resize!
, initialized with #undef
, and then use setindex!
to add elements to the particles
array. This approach also did not help and the runtime was still as shown in the figure above.
As a result, I thought to open this new thread here as the problem of general rise in a code runtime might be faced by others as well. I would appreciate very much your thoughts and suggestions on this issue.
Many thanks!