Zoom HPC with Julia: the n-body problem as an example
Last updated: January 12, 2023
Zoom session 3 โ part 1
Time:
2:30 pm Pacific Time.
Topic:
In this session, we will solve the n-body problem in Julia.
Sequential script
Julia script
seq.jl
##############################################################################
# Sequential implementation
##############################################################################
using BenchmarkTools
n = 10
x = 2rand(n, 3) .- 1
v = zeros(n, 3)
nout = 100
courant = 1e-3
eps = 0.001
v[:, 1] = 2 .* x[:, 2]
v[:, 2] = .- x[:, 1] ./ x[:, 2] .* v[:, 1]
xnew, vnew = zeros(n, 3), zeros(n, 3)
vhalf = zeros(n, 3)
step = Int(3e4)
history = zeros(n, 3, Int(step/nout)+1)
history[:, :, 1] = x
@btime for t in 1:step
force = zeros(n, 3)
tmin = 1.e10
for i in 1:n
for j in 1:n
if i != j
distSquared = sum((x[i, :] - x[j, :]).^2)
force[i, :] -= (x[i, :] - x[j, :]) / distSquared^1.5
tmin = min(tmin, sqrt((distSquared+eps) / sum((v[i, :] - v[j, :]).^2)))
end
end
end
dt = tmin * courant
# dt = tmin
for i in n
xnew[i, :] .= x[i, :] .+ v[i, :].*dt
vnew[i, :] .= v[i, :] .+ force[i, :].*dt
end
global x = xnew
global v = vnew
if (t+1)%nout == 0
history[:, :, trunc(Int, t/nout)+1] = x
end
end
sbatch script
seq.sh
#!/bin/bash
#SBATCH --time=5
#SBATCH --mem=2G
#SBATCH --output=%j.out
#SBATCH --error=%j.err
echo Sequential: running non parallel script
julia seq.jl
Shared memory script
Julia script
sha.jl
##############################################################################
# Shared memory implementation
##############################################################################
using Base.Threads
using BenchmarkTools
n = 10
x = 2rand(n, 3) .- 1
v = zeros(n, 3)
nout = 100
courant = 1e-3
eps = 0.001
v[:, 1] = 2 .* x[:, 2]
v[:, 2] = .- x[:, 1] ./ x[:, 2] .* v[:, 1]
xnew, vnew = zeros(n, 3), zeros(n, 3)
vhalf = zeros(n, 3)
step = Int(3e4)
history = zeros(n, 3, Int(step/nout)+1)
history[:, :, 1] = x
@btime @threads for t in 1:step
force = zeros(n, 3)
tmin = 1.e10
for i in 1:n
for j in 1:n
if i != j
distSquared = sum((x[i, :] - x[j, :]).^2)
force[i, :] -= (x[i, :] - x[j, :]) / distSquared^1.5
tmin = min(tmin, sqrt((distSquared+eps) / sum((v[i, :] - v[j, :]).^2)))
end
end
end
dt = tmin * courant
# dt = tmin
for i in n
xnew[i, :] .= x[i, :] .+ v[i, :].*dt
vnew[i, :] .= v[i, :] .+ force[i, :].*dt
end
global x = xnew
global v = vnew
if (t+1)%nout == 0
history[:, :, trunc(Int, t/nout)+1] = x
end
end
sbatch script
sha.sh
#!/bin/bash
#SBATCH --time=5
#SBATCH --cpus-per-task=4
#SBATCH --mem=8G
#SBATCH --output=%j.out
#SBATCH --error=%j.err
echo Shared memory: running parallel script on $SLURM_CPUS_PER_TASK cores
julia -t 4 sha.jl
Distributed memory script
Julia script
dis.jl
sbatch script
dis.sh
#!/bin/bash
#SBATCH --time=10
#SBATCH --nodes=2
#SBATCH --cpus-per-task=4
#SBATCH --mem=8G
#SBATCH --output=%j.out
#SBATCH --error=%j.err
echo Distributed memory: running parallel script on 2 nodes and $SLURM_CPUS_PER_TASK cores per node
julia -p 2 -t 4 dis.jl