Skip to content

Parallelize solve_problems - #195

Draft
MaxenceGollier wants to merge 6 commits into
JuliaSmoothOptimizers:mainfrom
MaxenceGollier:parallel
Draft

MaxenceGollier wants to merge 6 commits into
JuliaSmoothOptimizers:mainfrom
MaxenceGollier:parallel

Conversation

@MaxenceGollier

@MaxenceGollier MaxenceGollier commented Feb 10, 2026

Copy link
Copy Markdown
Contributor

@dpo, @tmigot

#120

(hopefully) supersedes #127, #167, #176.
To parallelize over solvers instead of problems, CUTEst problems make it very very difficult, i have tried multiple times but failed. I think it is fine just to parallelize over problems.

To make things clear,

  • I added a private function _run_problem which just performs one iteration of the loop.
  • I first make a serial run where first_problem is set to false to avoid race conditions on this variable and other variables accessed when first_problem is true.
  • I then make the parallel run.
  • I added a lock when we modify and read from stats to prevent race conditions.

@MaxenceGollier

Copy link
Copy Markdown
Contributor Author

The race condition causes issue, for example, see MaxenceGollier/Penelopt.jl#57. I will fix the BSD tests as well.

@tmigot tmigot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MaxenceGollier If I understand correctly you propose to do multi-threading over problems. This assumes that problems are thread-safe, which is the case for CUTEst and (in theory) OptimizationProblems.jl, however it also needs the solvers to be thread safe, which I don't think we really test.

If we are going for a multi-threaded version, I think it should be a different function than solve_problems also, because it will never be safe in general (for any set of problems, and any set of solvers).

Comment thread src/run_solver.jl
Comment on lines 89 to +90
stats = DataFrame(names .=> [T[] for T in types])
stats_lock = ReentrantLock()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to have one stats per thread and merge all of them in the end ?

@tmigot

tmigot commented Feb 11, 2026

Copy link
Copy Markdown
Member

The idea would be that your version is faster when it is possible, and #194 would be safer. So, both approaches might be complementary.

@MaxenceGollier

Copy link
Copy Markdown
Contributor Author

Hi @tmigot, i separated in two distinct functions. My issue is that there is a lot of repeated code which makes it harder to maintain...

@MaxenceGollier
MaxenceGollier marked this pull request as ready for review August 12, 2026 13:35
Copilot AI lite review requested due to automatic review settings August 12, 2026 13:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a threaded execution path for benchmarking by parallelizing solve_problems over problems, and wires it into bmark_solvers behind a new parallel keyword.

Changes:

  • Introduces solve_problems_parallel in src/run_solver.jl using Threads.@spawn and a lock to protect writes to the shared stats DataFrame.
  • Adds parallel::Bool=false to bmark_solvers to select solve_problems_parallel when multiple Julia threads are available.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/run_solver.jl Adds a new parallel solver runner and a locked per-problem execution helper.
src/bmark_solvers.jl Adds a parallel keyword to switch between serial and threaded benchmarking.
Suppressed comments (1)

src/run_solver.jl:330

  • _run_problem is called inside the spawned task, but there is no _run_problem definition in the codebase. This will throw a UndefVarError when the parallel section runs.
      _run_problem(

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/run_solver.jl Outdated
# Make a first serial run until first_problem is false
final_id = 0
for (id, problem) in enumerate(problems)
first_problem, nb_unsuccessful_since_start = _run_problem(
Comment thread src/run_solver.jl
problem,
stats::DataFrame,
solver,
solver_name::Symbol,
Comment thread src/run_solver.jl
Comment on lines +296 to +298
# Make a first serial run until first_problem is false
final_id = 0
for (id, problem) in enumerate(problems)
Comment thread src/bmark_solvers.jl
if parallel && Threads.nthreads() > 1
stats[name] = solve_problems_parallel(solver, name, args...; kwargs...)
else
parallel && @warn "SolverBenchmarks.jl: parallel is set to true but the number of threads is $(Threads.nthreads()). Running in serial mode."
@tmigot

tmigot commented Aug 30, 2026

Copy link
Copy Markdown
Member

@MaxenceGollier Sorry I have very limited time for JSO. But I'd be happy to make another round of review. What is the status here as I see some unadressed comments in the PR ?

@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 5.97015% with 63 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.40%. Comparing base (4c0fcd2) to head (987ec11).
⚠️ Report is 45 commits behind head on main.

Files with missing lines Patch % Lines
src/run_solver.jl 0.00% 62 Missing ⚠️
src/bmark_solvers.jl 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #195      +/-   ##
==========================================
- Coverage   76.71%   73.40%   -3.32%     
==========================================
  Files          12       10       -2     
  Lines         292      391      +99     
==========================================
+ Hits          224      287      +63     
- Misses         68      104      +36     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@MaxenceGollier

Copy link
Copy Markdown
Contributor Author

No problem @tmigot.

This is the current status of the PR.

I have coded a workflow in the repo : https://github.com/MaxenceGollier/Penelopt.jl that basically runs my benchmarks on each PR, using SolverBenchmark.jl.

I tried using this PR to make my benchmarks faster.
As it turns out, the PR works but my solver is actually not thread safe because I use MUMPS. Thefore, I switched to a different strategy and I am no longer using this.

@tmigot

tmigot commented Aug 30, 2026

Copy link
Copy Markdown
Member

Ok so we switch this to a draft waiting for an actual use ?

@MaxenceGollier
MaxenceGollier marked this pull request as draft August 30, 2026 18:57

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants