Skip to content

Commit 450eecf

Browse files
committed
Parallelize initialization of particles
1 parent 82dff1c commit 450eecf

File tree

3 files changed

+90
-13
lines changed

3 files changed

+90
-13
lines changed

src/PSOGPU.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module PSOGPU
33
using SciMLBase, StaticArrays, Setfield, KernelAbstractions
44
using QuasiMonteCarlo, Optimization, SimpleNonlinearSolve, ForwardDiff
55
import Adapt
6+
import Adapt: adapt
67
import Enzyme: autodiff_deferred, Active, Reverse
78
import KernelAbstractions: @atomic, @atomicreplace, @atomicswap
89
using QuasiMonteCarlo

src/solve.jl

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,49 @@ function SciMLBase.init(
1414
backend = opt.backend
1515
@assert prob.u0 isa SArray
1616

17-
## initialize cache
18-
1917
## Bounds check
2018
lb, ub = check_init_bounds(prob)
2119
lb, ub = check_init_bounds(prob)
2220
prob = remake(prob; lb = lb, ub = ub)
2321

24-
init_gbest, particles = init_particles(prob, opt, typeof(prob.u0))
22+
particles = KernelAbstractions.allocate(
23+
backend, SPSOParticle{typeof(prob.u0), eltype(typeof(prob.u0))}, opt.num_particles)
24+
kernel! = gpu_init_particles!(backend)
2525

26-
# TODO: Do the equivalent of cu()/roc()
27-
particles_eltype = eltype(particles) === Float64 ? Float32 : eltype(particles)
28-
gpu_particles = KernelAbstractions.allocate(backend,
29-
particles_eltype,
30-
size(particles))
31-
copyto!(gpu_particles, particles)
32-
gpu_init_gbest = KernelAbstractions.allocate(backend, typeof(init_gbest), (1,))
33-
copyto!(gpu_init_gbest, [init_gbest])
26+
kernel!(particles, prob, opt, typeof(prob.u0); ndrange = opt.num_particles)
27+
28+
best_particle = minimum(particles)
29+
_init_gbest = SPSOGBest(best_particle.best_position, best_particle.best_cost)
30+
31+
init_gbest = KernelAbstractions.allocate(backend, typeof(_init_gbest), (1,))
32+
copyto!(init_gbest, [_init_gbest])
3433
return PSOCache{
35-
typeof(prob), typeof(opt), typeof(gpu_particles), typeof(gpu_init_gbest)}(
36-
prob, opt, gpu_particles, gpu_init_gbest)
34+
typeof(prob), typeof(opt), typeof(particles), typeof(init_gbest)}(
35+
prob, opt, particles, init_gbest)
36+
end
37+
38+
function SciMLBase.reinit!(cache::PSOCache; kwargs...)
39+
reinit_cache!(cache, cache.alg)
40+
end
41+
42+
function reinit_cache!(cache::PSOCache, opt::ParallelPSOKernel)
43+
prob = cache.prob
44+
backend = opt.backend
45+
particles = cache.particles
46+
47+
kernel! = PSOGPU.gpu_init_particles!(backend)
48+
kernel!(particles, prob, opt, typeof(prob.u0); ndrange = opt.num_particles)
49+
50+
best_particle = minimum(particles)
51+
_init_gbest = SPSOGBest(best_particle.best_position, best_particle.best_cost)
52+
53+
copyto!(cache.gbest, [_init_gbest])
54+
55+
return nothing
56+
end
57+
58+
function SciMLBase.solve!(cache, args...; maxiters = 100, kwargs...)
59+
solve!(cache, cache.alg, args...; maxiters, kwargs...)
3760
end
3861

3962
function SciMLBase.solve!(

src/utils.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,59 @@ function uniform(dim::Int, lb::AbstractArray{T}, ub::AbstractArray{T}) where {T}
1111
return arr
1212
end
1313

14+
@kernel function gpu_init_particles!(particles, prob, opt, ::Type{T}) where {T <: SArray}
15+
i = @index(Global, Linear)
16+
17+
dim = length(prob.u0)
18+
lb = prob.lb
19+
ub = prob.ub
20+
cost_func = prob.f
21+
p = prob.p
22+
num_particles = opt.num_particles
23+
24+
if lb === nothing || (all(isinf, lb) && all(isinf, ub))
25+
gbest_position = StaticArrays.sacollect(T,
26+
ifelse(
27+
abs(prob.u0[i]) > 0, prob.u0[i] + rand(eltype(prob.u0)) * abs(prob.u0[i]),
28+
rand(eltype(prob.u0))) for i in 1:dim)
29+
else
30+
gbest_position = StaticArrays.sacollect(T, uniform_itr(dim, lb, ub))
31+
end
32+
33+
gbest_position = convert(T, gbest_position)
34+
gbest_cost = cost_func(gbest_position, p)
35+
if !isnothing(prob.f.cons)
36+
penalty = calc_penalty(gbest_position, prob, 1, opt.θ, opt.γ, opt.h)
37+
gbest_cost = cost_func(gbest_position, p) + penalty
38+
else
39+
gbest_cost = cost_func(gbest_position, p)
40+
end
41+
gbest_cost = cost_func(gbest_position, p)
42+
43+
if lb === nothing || (all(isinf, lb) && all(isinf, ub))
44+
position = StaticArrays.sacollect(T,
45+
ifelse(abs(prob.u0[i]) > 0,
46+
prob.u0[i] + rand(eltype(prob.u0)) * abs(prob.u0[i]),
47+
rand(eltype(prob.u0))) for i in 1:dim)
48+
else
49+
position = StaticArrays.sacollect(T, uniform_itr(dim, lb, ub))
50+
end
51+
52+
velocity = zero(T)
53+
54+
if !isnothing(prob.f.cons)
55+
penalty = calc_penalty(position, prob, 1, opt.θ, opt.γ, opt.h)
56+
cost = cost_func(position, p) + penalty
57+
else
58+
cost = cost_func(position, p)
59+
end
60+
61+
best_position = position
62+
best_cost = cost
63+
@inbounds particles[i] = SPSOParticle(
64+
position, velocity, cost, best_position, best_cost)
65+
end
66+
1467
function init_particles!(particles, prob, opt, ::Type{T}) where {T <: SArray}
1568
dim = length(prob.u0)
1669
lb = prob.lb

0 commit comments

Comments
 (0)