Hello!
I have a runnable MWE here, put into a small module to easily redefine struct as needed:
module ParticleSorting
export sort_particles_by_density
using StructArrays
using StaticArrays
using BenchmarkTools
using Random
# Define a simple particle struct
struct Particle
position :: SVector{2,Float64}
velocity :: SVector{2,Float64}
density :: Float64
index :: CartesianIndex{2}
boundary_bool :: Bool
end
# Function to create a StructArray with random data for demonstration
function create_particles(n)
positions = rand(SVector{2,Float64}, n)
velocities = rand(SVector{2,Float64}, n) * 100
densities = rand(n) * 1000
index = [CartesianIndex(rand(1:100), rand(1:100)) for _ in 1:n]
boundary_bool = rand(Bool, n)
StructArray{Particle}((position = positions, velocity = velocities, density = densities, index = index, boundary_bool = boundary_bool))
end
# Function to sort the StructArray by the density field
function sort_particles_by_index(particles)
sort!(particles, by = p -> p.index)
end
# Function to benchmark sorting
function benchmark_sorting(particles)
# The setup block: shuffle the particles array; this part is not timed
setup = (particles = shuffle!(particles);)
@benchmark sort_particles_by_index($particles) setup=$setup
end
end # module ParticleSorting
using .ParticleSorting
# Create a StructArray with random particles
particles = ParticleSorting.create_particles(100000)
# Benchmark sorting by density
benchmark_result = ParticleSorting.benchmark_sorting(particles)
# Print benchmark result
display(benchmark_result)
My need is that I have a list of vectors which I need to sort based on the index
field. Iβve found it is faster to put everything in a StructVector
and call sort!
on that. My benchmark result is something like this:
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
Range (min β¦ max): 125.900 ΞΌs β¦ 5.389 ms β GC (min β¦ max): 0.00% β¦ 0.00%
Time (median): 132.100 ΞΌs β GC (median): 0.00%
Time (mean Β± Ο): 164.548 ΞΌs Β± 103.733 ΞΌs β GC (mean Β± Ο): 0.00% Β± 0.00%
βββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββ
β
ββ
βββ
ββ
β
ββ
β
β
βββββ
ββββ β
126 ΞΌs Histogram: log(frequency) by time 480 ΞΌs <
Memory estimate: 0 bytes, allocs estimate: 0.
Which is quite amazing, but I wondered if it can be done faster?
Secondly, after having sorted the values I want to update a value:
julia> particles[1].velocity = particles[2].velocity
ERROR: setfield!: immutable struct of type Particle cannot be changed
Stacktrace:
[1] setproperty!(x::Main.ParticleSorting.Particle, f::Symbol, v::StaticArraysCore.SVector{2, Float64})
@ Base .\Base.jl:41
[2] top-level scope
@ REPL[4]:1
I think the point of a StructVector is a bit lost, if I canβt update values at some point, so I am curios as to how to do this properly? I understand that the SVector it self is immutable, I donβt understand why I canΒ΄t replace it with a new one in the StructVector
.
Kind regards