Multiple threading
The multi-threading computation is built upon Julia's @threads
macro.
Base.Threads.@threads for ... end
It provides an OpenMP type parallelization. The iteration space is splitted among multiple tasks and those tasks are parallelized on threads according to a scheduling policy. A barrier is placed at the end of the loop which waits for all tasks to finish execution.
In Kinetic, @threads
is set in front of the loops for reconstruction, evolution and update. For example, the evaluation of fluxes is conducted as follows.
@inbounds Threads.@threads for i = idx0:idx1
flux_gks!(
face[i].fw,
ctr[i-1].w .+ 0.5 .* ctr[i-1].dx .* ctr[i-1].sw,
ctr[i].w .- 0.5 .* ctr[i].dx .* ctr[i].sw,
KS.gas.γ,
KS.gas.K,
KS.gas.μᵣ,
KS.gas.ω,
dt,
0.5 * ctr[i-1].dx,
0.5 * ctr[i].dx,
ctr[i-1].sw,
ctr[i].sw,
)
end
It automatically makes use of multiple threading if Julia is initialized with
julia -t n
Besides of @threads
, finer dispatch can be made with @spawn
macro.
Base.Threads.@spawn
It creates and runs a task on any available thread. To wait for the task to finish, call wait
on the result of this macro, or call fetch to wait and then obtain its return value. Values can be interpolated into @spawn
via $
, which copies the value directly into the constructed underlying closure. It allows user to insert the value of a variable, isolating the aysnchronous code from changes to the variable's value in the current task. This can be conduct with the low-level reconstruction, flux and step functions.