-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhances solver with plateau detection, adds missing Python options #80
Enhances solver with plateau detection, adds missing Python options #80
Conversation
solve_terminate.go
Outdated
} | ||
|
||
// IsStop returns true if the solver should stop due to a detected plateau. | ||
func (t *plateauTracker) IsStop(iterations int, elapsed time.Duration) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename the function to ShouldStop
? Also because we have the concept of a Stop
in nextroute. But what the function does is to decide if the solver should stop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good call. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed it to ShouldTerminate
to stay away from the Stop
double meaning. 😊
solve_solver_parallel.go
Outdated
@@ -351,6 +363,12 @@ func (s *parallelSolverImpl) Solve( | |||
if totalIterations.Add(1) >= int64(interpretedParallelSolveOptions.Iterations) { | |||
cancel() | |||
} | |||
if s.plateauTracker.IsStop( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gets called very often. Maybe we can add a benchmark test that ensures that IsStop
never allocates and does totalIterations.Load()
cost a lot? Because we can reuse the result of totalIterations.Add(1)
then we don't have to lock again (if Load()
locks).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking the same thing. Now that you mention it, I think avoiding the double atomic call is better. I doubt that it makes concurrency issues worse (which I was worried about before for some reason), but may even make it better. For sure, it will avoid extra cost (however small they may be).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify, you are only worried about a potential performance loss for when a user activates plateau tracking, right? (it's off by default - so shouldn't cause a regression)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think the code in the hot path of the solver needs to be as fast as possible and ideally should not allocate (which it does not, unless some interface related hidden allocations are triggered). With the change of how the iteration count is retrieved the tracker will have minimal overhead if it is disabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
Description
Introduced plateau detection for solvers, allowing termination based on lack of improvement over time or iterations.
Changes
PlateauOptions
struct for plateau detection configuration.github.com/nextmv-io/sdk
dependency to include an upstream golden file test fix.Preview
This PR adds the option to define stopping criteria when the solve process (value progression / improvement) starts to stagnate / converge.
This can be done via the typical
nextroute.ParallelSolveOptions
struct or simply via the options (applicable for most cases):