Repository navigation
Run HybridPSO's L-BFGS phase in lockstep across particles - #153
Closed
AdityaPandeyCN wants to merge 8 commits into
Closed
AdityaPandeyCN wants to merge 8 commits into
AdityaPandeyCN wants to merge 8 commits into
Conversation
Replace the one-thread-per-particle `lbfgs_run!` kernel with a lockstep projected L-BFGS: the iteration loop runs on the host and each step is a few short broadcasts over all particles (unrolled two-loop direction, 16-step parallel line search, one forward-mode directional derivative per thread). The memory size comes from SimpleLBFGS's threshold. Coordinates with a finite box are rescaled to [0, 1]; the ±Inf bounds `init` stores for unbounded problems leave a coordinate unscaled.
AdityaPandeyCN
added a commit
to AdityaPandeyCN/SciMLBenchmarks.jl
that referenced
this pull request
Oct 13, 2026
…-BFGS branch Point ParallelParticleSwarms at the unmerged lockstep-lbfgs branch (SciML/ParallelParticleSwarms.jl#153) so CI measures the new L-BFGS phase. Switch back to a registered release once it is merged.
Comment on lines
+7
to
+15
| # Lockstep projected L-BFGS for HybridPSO's local phase. All particles take each step | ||
| # together: the iteration loop runs on the host and every step is a few short | ||
| # broadcasts over all particles, instead of one long divergent thread per particle. | ||
| # Internally a coordinate with a finite box works in y = (x - lb) / (ub - lb) clamped to | ||
| # [0, 1]; any other coordinate (`init` stores a missing bound as ±Inf) is left as is and | ||
| # only clamped to the bound it has. | ||
|
|
||
| struct LBFGSState{D, T, M} | ||
| x::SVector{D, T} |
Member
There was a problem hiding this comment.
Why not just put the SimpleOptimization call in a kernel call?
… loop The loop stopped once any particle's cost fell below abstol, which only works when the minimum is 0: on BBOB F8 (f_opt = -154.5) it stopped after the first iteration. Stop instead once every particle's projected gradient, in x units, is within max(abstol, sqrt(eps)), as SimpleOptimization's L-BFGS did. Also tidy the loop into _STEPS, _CURVATURE_TOL and _lbfgs_update.
The broadcast over SVectors with a captured closure could not be compiled inside the CUDA mapreduce kernel.
HybridPSO's local phase goes back to SimpleOptimization's projected L-BFGS with the Strong-Wolfe line search, as on master. Only the execution changes: each particle's `_lbfgs` run is cut at its objective/gradient evaluations, and every host step evaluates all particles' pending points together, then advances each one through `_lbfgs`'s own control flow to its next evaluation. With AutoForwardDiff the gradient is split into one direction per thread; other AD types use the per-particle gradient as before. This drops the best-of-16-steps search, the normalized coordinates, the history reset on rejected steps and the projected-gradient abstol from the earlier commits, and restores the `linesearch` keyword. `maxtime` is kept. A test checks the lockstep results bit for bit against master's per-thread `_lbfgs` kernel on Rosenbrock and BBOB F8.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Runs HybridPSO's L-BFGS phase in lockstep across particles. The algorithm is unchanged from
main: SimpleOptimization's projected L-BFGS with LineSearch's Strong-Wolfe search. Only the execution changes.Each particle's
_lbfgsrun is cut at its objective/gradient evaluations. Every host step evaluates all particles' pending points together (f, plus the gradient as one thread per (particle, direction) withAutoForwardDiff, or per particle for other AD types). It then advances each particle through_lbfgs's own control flow to its next evaluation. Finished particles pass through unchanged. Results go into the sameresult/result_fxarrays as before, and the rest ofsolve!is as onmain, including thelinesearchkeyword.maxtimekeyword (defaultnothing) stops the local phase after that many seconds.LinearAlgebramoves from test extras to[deps], sodot/normare the ones_lbfgsuses.What
_lbfgsdoes (SimpleOptimization 2.0.1, LineSearch 0.1.19)[lb, ub]. The direction is zeroed in coordinates that point out of the box at an active bound. The line search'sα_maxis capped at the largest step that stays in the box. The accepted point is clamped again.M = threshold(s, y) pairs, scaled bys'y / y'yof the newest pair. If the direction is not a descent direction, it falls back to projected-gand restarts the history count. A pair is stored only ifs'y > sqrt(eps) * max(‖s‖‖y‖, eps)and is finite; otherwise the history count resets.α_init, doubles up toα_max, and accepts a step blocked atα_maxon Armijo alone. Zoom uses cubic interpolation kept 1% inside the bracket.maxitersandzoom_maxitersbound the two loops.tol = max(max(abstol, sqrt(eps)), reltol * initial projected-gradient max-norm). It stops when the projected gradient's max-norm is at mosttol, aftermaxitersiterations, on a non-finite f or gradient, or when the direction's max-norm is at mosteps.Tests
test/lbfgs.jlchecks that final positions and costs are bit-identical tomain's per-thread_lbfgskernel. Cases: Rosenbrock (unbounded, bounded, active bound), BBOB F8 in 10D (bounded and unbounded), Float64 and Float32, andAutoForwardDiff,AutoEnzymeandNoAD.StaticArrays'
dotis a@simdloop, so its rounding depends on where it is inlined. Even_lbfgsin a kernel and on the host differ in the last bits. For this test only,dotis replaced by the same sum without@simd, and the replacement is removed afterwards.The bounded-Rosenbrock and
maxtimetests are kept.The
block argmin matches brute forceCUDA failures also happen onmain.