Black-Box Global Optimizer Benchmarks
In this benchmark we will run the BlackboxGlobalOptimization.jl benchmarks, a set of global optimization benchmarks on the Optimization.jl interface that test a wide variety of behaviors. This tests both iterations and wall-clock time vs accuracy, i.e. for a given budget (in iterations or time), what percentage of problems from the set is a solver able to solve. This gives a global view of which methods are the most efficient at finding difficult global optima.
Setup
using BlackBoxOptimizationBenchmarking, Plots, Optimization, Memoize, Statistics
import BlackBoxOptimizationBenchmarking: Chain, BenchmarkSetup, BenchmarkResults,
BBOBFunction, FunctionCallsCounter, solve_problem, pinit, compute_CI
const BBOB = BlackBoxOptimizationBenchmarking
using OptimizationBBO, OptimizationOptimJL, OptimizationEvolutionary, OptimizationNLopt
using OptimizationMetaheuristics, OptimizationNOMAD, OptimizationPRIMA, OptimizationOptimisers, OptimizationSciPy, OptimizationPyCMAWe define a time-to-success benchmarking framework. For each (optimizer, function, trial), we run the optimizer once with a large iteration budget and wrap the objective function to detect the first evaluation that achieves the success criterion. The wall-clock time at that moment is recorded as the "time to success". From these times we build a CDF: for a given wall-time budget T, what fraction of (function, trial) pairs were solved?
function make_success_tracker(f_raw, f_opt, Δf)
t0 = Ref(time())
time_to_success = Ref(Inf)
function tracked_f(u)
val = f_raw(u)
if val < Δf + f_opt && time_to_success[] == Inf
time_to_success[] = time() - t0[]
end
return val
end
return tracked_f, t0, time_to_success
end
function solve_problem_timed(optimizer::BenchmarkSetup, tracked_f, D::Int, run_length::Int;
u0 = pinit(D))
method = optimizer.method
optf = OptimizationFunction((u, _) -> tracked_f(u), AutoForwardDiff())
if optimizer.isboxed
prob = OptimizationProblem(optf, u0, lb = fill(-5.5, D), ub = fill(5.5, D))
else
prob = OptimizationProblem(optf, u0)
end
sol = Optimization.solve(prob, method; maxiters = run_length)
sol
end
function solve_problem_timed(m::Chain, tracked_f, D::Int, run_length::Int)
rl1 = round(Int, m.p * run_length)
rl2 = run_length - rl1
sol = solve_problem_timed(m.first, tracked_f, D, rl1)
xinit = sol.u
sol = solve_problem_timed(m.second, tracked_f, D, rl2; u0 = xinit)
end
function benchmark_time_to_success(
optimizer::Union{Chain, BenchmarkSetup}, f::BBOBFunction;
Ntrials::Int = 20, dimension::Int = 3, Δf::Real = 1e-6, max_run_length::Int = 100_000
)
times = Float64[]
for i in 1:Ntrials
tracked_f, t0_ref, tts_ref = make_success_tracker(f, f.f_opt, Δf)
try
t0_ref[] = time()
sol = solve_problem_timed(optimizer, tracked_f, dimension, max_run_length)
push!(times, tts_ref[])
catch err
push!(times, Inf)
@warn(string(optimizer, " failed: ", err))
end
end
return times
end
benchmark_time_to_success(optimizer, f; kwargs...) =
benchmark_time_to_success(BenchmarkSetup(optimizer), f; kwargs...)
function benchmark_time_to_success(
optimizer::Union{Chain, BenchmarkSetup}, funcs::Vector{BBOBFunction};
Ntrials::Int = 20, dimension::Int = 3, Δf::Real = 1e-6, max_run_length::Int = 100_000
)
all_times = Float64[]
for f in funcs
append!(all_times, benchmark_time_to_success(
optimizer, f; Ntrials, dimension, Δf, max_run_length))
end
return all_times
end
benchmark_time_to_success(optimizer, funcs::Vector{BBOBFunction}; kwargs...) =
benchmark_time_to_success(BenchmarkSetup(optimizer), funcs; kwargs...)
function success_rate_cdf(all_times::Vector{Float64}, time_thresholds::AbstractVector{Float64})
N = length(all_times)
return [count(x -> x <= t, all_times) / N for t in time_thresholds]
endsuccess_rate_cdf (generic function with 1 method)chain = (t;
isboxed = false) -> Chain(
BenchmarkSetup(t, isboxed = isboxed),
BenchmarkSetup(NelderMead(), isboxed = false),
0.9
)
dimension = 3
test_functions = BBOB.bbob_suite(Val(dimension))
run_length = round.(Int, 10 .^ LinRange(1, 5, 30))
@memoize run_bench(algo) = BBOB.benchmark(
setup[algo], test_functions, run_length, Ntrials = 40)
@memoize run_tts(algo) = benchmark_time_to_success(
setup[algo], test_functions, Ntrials = 40, dimension = dimension)run_tts (generic function with 1 method)setup = Dict(
"NelderMead" => NelderMead(),
#Optim.BFGS(),
#"NLopt.GN_MLSL_LDS" => chain(NLopt.GN_MLSL_LDS(), isboxed=true), # gives me errors
"NLopt.GN_CRS2_LM()" => chain(NLopt.GN_CRS2_LM(), isboxed = true),
"NLopt.GN_DIRECT()" => chain(NLopt.GN_DIRECT(), isboxed = true),
"NLopt.GN_ESCH()" => chain(NLopt.GN_ESCH(), isboxed = true),
"OptimizationEvolutionary.GA()" => chain(OptimizationEvolutionary.GA(), isboxed = true),
"OptimizationEvolutionary.DE()" => chain(OptimizationEvolutionary.DE(), isboxed = true),
"OptimizationEvolutionary.ES()" => chain(OptimizationEvolutionary.ES(), isboxed = true),
"Optim.SAMIN" => chain(SAMIN(verbosity = 0), isboxed = true),
"BBO_adaptive_de_rand_1_bin" => chain(BBO_adaptive_de_rand_1_bin(), isboxed = true),
"BBO_adaptive_de_rand_1_bin_radiuslimited" => chain(
BBO_adaptive_de_rand_1_bin_radiuslimited(), isboxed = true), # same as BBO_adaptive_de_rand_1_bin
"BBO_separable_nes" => chain(BBO_separable_nes(), isboxed = true),
"BBO_de_rand_2_bin" => chain(BBO_de_rand_2_bin(), isboxed = true),
#"BBO_xnes" => chain(BBO_xnes(), isboxed=true), # good but slow
#"BBO_dxnes" => chain(BBO_dxnes(), isboxed=true),
"OptimizationMetaheuristics.ECA" => chain(OptimizationMetaheuristics.ECA(), isboxed = true),
#"OptimizationMetaheuristics.CGSA" => () -> chain(OptimizationMetaheuristics.CGSA(), isboxed=true), #give me strange results
"OptimizationMetaheuristics.DE" => chain(OptimizationMetaheuristics.DE(), isboxed=true),
"Optimisers.AdamW" => chain(Optimisers.AdamW(), isboxed=false),
"Optimisers.RMSProp" => chain(Optimisers.RMSProp(), isboxed=false),
# SciPy global optimizers
"ScipyDifferentialEvolution" => chain(ScipyDifferentialEvolution(), isboxed=true),
#"ScipyBasinhopping" => chain(ScipyBasinhopping(), isboxed=true),
#"ScipyDualAnnealing" => chain(ScipyDualAnnealing(), isboxed=true), # taking long time
"ScipyShgo" => chain(ScipyShgo(), isboxed=true),
"ScipyDirect" => chain(ScipyDirect(), isboxed=true),
"ScipyBrute" => chain(ScipyBrute(), isboxed=true),
# "NOMADOpt" => chain(NOMADOpt()), too much printing
# "OptimizationPRIMA.UOBYQA()" => chain(OptimizationPRIMA.UOBYQA()), :StackOverflowError?
# "OptimizationPRIMA.NEWUOA()" => OptimizationPRIMA.UOBYQA(),
#
)Dict{String, Any} with 20 entries:
"OptimizationEvolutionar… => Chain(GA → NelderMead)…
"BBO_separable_nes" => Chain(BBO_separable_nes → NelderMead)…
"NelderMead" => NelderMead{AffineSimplexer, AdaptiveParamete
rs}(…
"BBO_adaptive_de_rand_1_… => Chain(BBO_adaptive_de_rand_1_bin → NelderMea
d)…
"BBO_adaptive_de_rand_1_… => Chain(BBO_adaptive_de_rand_1_bin_radiuslimit
ed →…
"BBO_de_rand_2_bin" => Chain(BBO_de_rand_2_bin → NelderMead)…
"NLopt.GN_DIRECT()" => Chain(Algorithm → NelderMead)…
"NLopt.GN_ESCH()" => Chain(Algorithm → NelderMead)…
"OptimizationMetaheurist… => Chain(Algorithm → NelderMead)…
"ScipyShgo" => Chain(ScipyShgo → NelderMead)…
"OptimizationEvolutionar… => Chain(ES → NelderMead)…
"Optimisers.AdamW" => Chain(AdamW → NelderMead)…
"ScipyDirect" => Chain(ScipyDirect → NelderMead)…
"ScipyDifferentialEvolut… => Chain(ScipyDifferentialEvolution → NelderMea
d)…
"ScipyBrute" => Chain(ScipyBrute → NelderMead)…
"OptimizationEvolutionar… => Chain(DE → NelderMead)…
"Optimisers.RMSProp" => Chain(RMSProp → NelderMead)…
"OptimizationMetaheurist… => Chain(Algorithm → NelderMead)…
"NLopt.GN_CRS2_LM()" => Chain(Algorithm → NelderMead)…
"Optim.SAMIN" => Chain(SAMIN → NelderMead)…Test one optimizer
@time b = BBOB.benchmark(
chain(OptimizationMetaheuristics.CGSA(), isboxed = true),
test_functions[1:10], 100:500:10_000, Ntrials = 10
)
plot(b)38.489459 seconds (135.07 M allocations: 6.477 GiB, 4.88% gc time, 83.32%
compilation time: 3% of which was recompilation)
Test one test function (Rastrigin)
Δf = 1e-6
# The BBOBFunction contour recipe is 2-D, so use the 2-D instance of F3 (Rastrigin).
f = BBOB.bbob_suite(Val(2))[3]
single_setup = BenchmarkSetup(NLopt.GN_CRS2_LM(), isboxed = true)
sol = [BBOB.solve_problem(single_setup, f, 2, 5_000) for in in 1:10]
@info [sol.objective < Δf + f.f_opt for sol in sol]
p = plot(f, size = (600, 600), zoom = 1.5)
for sol in sol
scatter!(sol.u[1:1], sol.u[2:2], label = "", c = "blue",
marker = :xcross, markersize = 5, markerstrokewidth = 0)
end
p
Test all (iterations)
results = Array{BBOB.BenchmarkResults}(undef, length(setup))
algorithms = collect(keys(setup))
Threads.@threads for i in eachindex(algorithms)
algo = algorithms[i]
if !startswith(algo, "Scipy")
results[i] = run_bench(algo)
end
end
# PythonCall can segfault when these SciPy solves run on different Julia threads.
for (i, algo) in enumerate(algorithms)
if startswith(algo, "Scipy")
results[i] = run_bench(algo)
end
end
results20-element Vector{BlackBoxOptimizationBenchmarking.BenchmarkResults}:
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.00375, 0.0075, 0.00875, 0.005, 0.01, 0.01, 0.02625, 0.035
, 0.045, 0.0475 … 0.54375, 0.53, 0.55625, 0.53875, 0.5475, 0.545, 0.55125
, 0.5575, 0.5475, 0.5475]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.0175, 0.03, 0.0375, 0.04625, 0.0475, 0.05, 0.0725, 0.1237
5, 0.20125, 0.26375 … 0.5875, 0.60875, 0.60875, 0.59125, 0.5825, 0.6025,
0.6125, 0.605, 0.60625, 0.59875]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.02, 0.0325, 0.0325, 0.045, 0.05125, 0.0575, 0.10375, 0.15
5, 0.23625, 0.38 … 0.5375, 0.55125, 0.5425, 0.54875, 0.53625, 0.545, 0.54
125, 0.53875, 0.54, 0.54375]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.00375, 0.0075, 0.0025, 0.01, 0.01125, 0.01625, 0.025, 0.0
4, 0.04875, 0.0525 … 0.735, 0.81625, 0.84875, 0.91875, 0.94625, 0.9775, 0
.99, 0.99875, 1.0, 0.99875]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.0025, 0.00375, 0.00375, 0.0125, 0.01375, 0.015, 0.03, 0.0
4, 0.04375, 0.04875 … 0.76375, 0.83125, 0.91375, 0.9575, 0.9725, 0.97125,
0.97, 0.97, 0.96625, 0.9575]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.00625, 0.0025, 0.0075, 0.0025, 0.01375, 0.0225, 0.03375,
0.03875, 0.0475, 0.0475 … 0.68625, 0.775, 0.79375, 0.84125, 0.9, 0.9475,
0.94125, 0.9525, 0.95625, 0.96625]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.0, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05
… 0.65, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.0025, 0.0025, 0.00625, 0.01, 0.00875, 0.015, 0.01875, 0.0
275, 0.04, 0.05 … 0.55125, 0.58875, 0.59875, 0.62, 0.61625, 0.63, 0.635,
0.6425, 0.66125, 0.6425]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.04125, 0.05, 0.05, 0.05, 0.05, 0.05, 0.1, 0.1, 0.1, 0.1
… 0.5, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25
… 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.00125, 0.00125, 0.0, 0.0, 0.00125, 0.0025, 0.00625, 0.013
75, 0.025, 0.03875 … 0.53375, 0.5375, 0.53375, 0.55, 0.54875, 0.5475, 0.5
4125, 0.5325, 0.53375, 0.55]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.00125, 0.0, 0.0, 0.00125, 0.005, 0.00375, 0.01125, 0.02,
0.02875, 0.03625 … 0.54125, 0.5475, 0.54875, 0.54625, 0.54875, 0.545, 0.5
525, 0.53, 0.54375, 0.56125]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05
… 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.39125, 0.395, 0.4275, 0.41125, 0.45875, 0.4725, 0.46125,
0.45875, 0.49125, 0.48875 … 0.7025, 0.71125, 0.725, 0.7075, 0.71, 0.6875,
0.6925, 0.68375, 0.6975, 0.71125]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 … 0.55,
0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.05, 0.05, 0.05, 0.05, 0.0525, 0.05625, 0.12875, 0.25875,
0.34125, 0.3875 … 0.6775, 0.68875, 0.69375, 0.695, 0.695, 0.69125, 0.6762
5, 0.69375, 0.69125, 0.7025]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.0, 0.0, 0.00125, 0.0, 0.00375, 0.0075, 0.00875, 0.01375,
0.0225, 0.02625 … 0.53, 0.545, 0.5475, 0.53625, 0.55875, 0.54875, 0.54875
, 0.54125, 0.545, 0.55]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.045, 0.05, 0.05, 0.05, 0.05, 0.05, 0.1, 0.1, 0.1, 0.1 …
0.45, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.00375, 0.00125, 0.0025, 0.0075, 0.0125, 0.03875, 0.0475,
0.0475, 0.05, 0.05125 … 0.77625, 0.7775, 0.78125, 0.7825, 0.7875, 0.7975,
0.77, 0.7825, 0.79875, 0.77]
BenchmarkResults :
Run length : [10, 14, 19, 26, 36, 49, 67, 92, 127, 174 … 5736, 7880, 1082
6, 14874, 20434, 28072, 38566, 52983, 72790, 100000]
Success rate : [0.00375, 0.00625, 0.01625, 0.01875, 0.0275, 0.0425, 0.0475,
0.04875, 0.05, 0.05125 … 0.63375, 0.70875, 0.72875, 0.7425, 0.79625, 0.7
75, 0.77125, 0.78, 0.77625, 0.78]Success Rate vs. Iterations
# Define marker shapes and line styles for accessibility (colorblind-friendly)
const MARKERS = [:circle, :diamond, :utriangle, :square, :star5, :dtriangle, :pentagon,
:hexagon, :cross, :xcross, :rtriangle, :ltriangle, :star4, :star8, :heptagon, :octagon,
:vline, :hline, :+, :x]
const LINESTYLES = [:solid, :dash, :dot, :dashdot, :dashdotdot]
labels = collect(keys(setup))
idx = sortperm([b.success_rate[end] for b in results], rev = true)
p = plot(xscale = :log10, legend = :outerright,
size = (700, 350), margin = 10Plots.px, dpi = 200)
for (j, i) in enumerate(idx)
plot!(results[i], label = labels[i], showribbon = false,
lw = 2.5, xlim = (1, 1e5), x = :run_length,
markershape = MARKERS[mod1(j, length(MARKERS))],
linestyle = LINESTYLES[mod1(j, length(LINESTYLES))],
markersize = 4, markerstrokewidth = 0)
end
p
Test all (wall-clock time to success)
For the time-based benchmark, each optimizer is run once with a large iteration budget (100,000 iterations) per (function, trial) pair. The objective function is wrapped to detect the first evaluation that achieves the success criterion (objective < Δf + f_opt) and record the wall-clock time at that moment. This gives a true "time to success" for each trial, from which we build a CDF.
tts_results = Dict{String, Vector{Float64}}()
for algo in keys(setup)
tts_results[algo] = run_tts(algo)
endSuccess Rate vs. Wall-Clock Time
This plot is the time-based analog of the iteration plot above. The x-axis is a wall-clock time budget; for each budget T, the y-axis shows what fraction of (function, trial) pairs the optimizer solved within T seconds. Unlike the iteration plot, this accounts for per-iteration cost differences between algorithms.
labels = collect(keys(setup))
# Determine time thresholds from data
all_finite = filter(isfinite, vcat(values(tts_results)...))
t_lo = minimum(all_finite) / 2
t_hi = maximum(all_finite) * 2
time_thresholds = 10 .^ range(log10(t_lo), log10(t_hi), length = 50)
cdfs = Dict(algo => success_rate_cdf(tts_results[algo], time_thresholds) for algo in labels)
idx = sortperm([cdfs[l][end] for l in labels], rev = true)
p = plot(xscale = :log10, legend = :outerright,
size = (700, 350), margin = 10Plots.px, dpi = 200,
xlabel = "Wall time (s)", ylabel = "Success rate", ylim = (0, 1))
for (j, i) in enumerate(idx)
plot!(time_thresholds, cdfs[labels[i]], label = labels[i], lw = 2.5,
markershape = MARKERS[mod1(j, length(MARKERS))],
linestyle = LINESTYLES[mod1(j, length(LINESTYLES))],
markersize = 4, markerstrokewidth = 0)
end
p
Success Rate per Function Heatmap
success_rate_per_function = reduce(hcat, b.success_rate_per_function for b in results)
idx = sortperm(mean(success_rate_per_function, dims = 1)[:], rev = false)
idxfunc = sortperm(mean(success_rate_per_function, dims = 2)[:], rev = true)
idxfunc = 1:length(test_functions)
p = heatmap(
string.(test_functions)[idxfunc], labels[idx], success_rate_per_function[idxfunc, idx]',
cmap = :RdYlGn,
xticks = :all,
yticks = :all,
xrotation = 45,
dpi = 200
)
Distance to Minimizer vs. Iterations
labels = collect(keys(setup))
idx = sortperm([b.distance_to_minimizer[end] for b in results], rev = false)
p = plot(xscale = :log10, legend = :outerright,
size = (900, 500), margin = 10Plots.px, ylim = (0, 5))
for (j, i) in enumerate(idx)
plot!(
results[i].run_length, results[i].distance_to_minimizer, label = labels[i],
showribbon = false, lw = 2, xlim = (1, 1e5),
xlabel = "Iterations", ylabel = "Mean distance to minimum",
markershape = MARKERS[mod1(j, length(MARKERS))],
linestyle = LINESTYLES[mod1(j, length(LINESTYLES))],
markersize = 4, markerstrokewidth = 0
)
end
p
Relative Runtime
ref = findfirst("NelderMead" .== labels)
runtimes = getfield.(results, :runtime)
runtimes = runtimes ./ runtimes[ref]
bar(
labels, runtimes, xrotation = :45, xticks = :all, ylabel = "Run time relative to NM",
yscale = :log10, yticks = [0.1, 1, 10, 100],
legend = false, margin = 25Plots.px
)
Appendix
These benchmarks are a part of the SciMLBenchmarks.jl repository, found at: https://github.com/SciML/SciMLBenchmarks.jl. For more information on high-performance scientific machine learning, check out the SciML Open Source Software Organization https://sciml.ai.
To locally run this benchmark, do the following commands:
using SciMLBenchmarks
SciMLBenchmarks.weave_file("benchmarks/GlobalOptimization","blackbox_global_optimizers.jmd")Computer Information:
Julia Version 1.12.7
Commit 6d172b025e4 (2026-08-15 08:05 UTC)
Build Info:
Official https://julialang.org release
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 128 × AMD EPYC 7502 32-Core Processor
WORD_SIZE: 64
LLVM: libLLVM-18.1.7 (ORCJIT, znver2)
GC: Built with stock GC
Threads: 128 default, 1 interactive, 128 GC (on 128 virtual cores)
Environment:
JULIA_CONDAPKG_BACKEND = Null
JULIA_LOAD_PATH = @:@stdlib
JULIA_PYTHONCALL_EXE = /home/crackauc/.cache/sciml-benchmarks/globalopt-python/bin/python
JULIA_NUM_THREADS = auto
Package Information:
Status `~/github-runners/amdci3-1/_work/SciMLBenchmarks.jl/SciMLBenchmarks.jl/benchmarks/GlobalOptimization/Project.toml`
[4552ee2b] BlackBoxOptimizationBenchmarking v2.0.1
[c03570c3] Memoize v0.4.4
⌃ [7f7a1694] Optimization v5.4.0
⌃ [3e6eede4] OptimizationBBO v0.4.5
⌃ [cb963754] OptimizationEvolutionary v0.4.6
⌃ [3aafef2f] OptimizationMetaheuristics v0.3.4
⌃ [4e6fcdb7] OptimizationNLopt v0.3.8
⌃ [2cab0595] OptimizationNOMAD v0.3.4
⌃ [36348300] OptimizationOptimJL v0.4.8
⌃ [42dfb2eb] OptimizationOptimisers v0.3.15
⌃ [72f8369c] OptimizationPRIMA v0.3.4
⌃ [fb0822aa] OptimizationPyCMA v1.2.0
⌃ [cce07bd8] OptimizationSciPy v0.4.5
[91a5bcdd] Plots v1.41.7
[31c91b34] SciMLBenchmarks v0.2.1 [loaded: `/home/crackauc/github-runners/amdci3-1/_work/SciMLBenchmarks.jl/SciMLBenchmarks.jl/src/SciMLBenchmarks.jl` (v0.2.1) expected `/home/crackauc/.julia/packages/SciMLBenchmarks/ceJyd/src/SciMLBenchmarks.jl` (v0.2.1)]
Info Packages marked with ⌃ have new versions available and may be upgradable.And the full manifest:
Status `~/github-runners/amdci3-1/_work/SciMLBenchmarks.jl/SciMLBenchmarks.jl/benchmarks/GlobalOptimization/Manifest.toml`
[47edcb42] ADTypes v1.24.0
[14f7f29c] AMD v0.5.4
[1520ce14] AbstractTrees v0.4.5
[7d9f7c33] Accessors v0.1.45
[79e6a3ab] Adapt v4.7.1
[66dad0bd] AliasTables v1.1.3
[4fba245c] ArrayInterface v7.30.2
[a134a8b2] BlackBoxOptim v0.6.12
[4552ee2b] BlackBoxOptimizationBenchmarking v2.0.1
[fa961155] CEnum v0.5.0
[d360d2e6] ChainRulesCore v1.26.1
[523fee87] CodecBzip2 v0.8.5
[944b1d66] CodecZlib v0.7.9
[35d6a980] ColorSchemes v3.31.0
[3da002f7] ColorTypes v0.12.1
[c3611d14] ColorVectorSpace v0.11.0
[5ae59095] Colors v0.13.1
[861a8166] Combinatorics v1.1.0
[38540f10] CommonSolve v0.2.14
[bbf7d656] CommonSubexpressions v0.3.1
[34da2185] Compat v4.18.1
[a33af91c] CompositionsBase v0.1.2
⌃ [992eb4ea] CondaPkg v0.2.33
[88cd18e8] ConsoleProgressMonitor v0.1.2
[187b0558] ConstructionBase v1.6.0
[d38c429a] Contour v0.6.3
[9a962f9c] DataAPI v1.16.0
[864edb3b] DataStructures v0.19.6
[e2d170a0] DataValueInterfaces v1.0.0
[8bb1440f] DelimitedFiles v1.9.1
[163ba53b] DiffResults v1.1.0
[b552c78f] DiffRules v1.16.0
[a0c0ee7d] DifferentiationInterface v0.7.21
[b4f34e82] Distances v0.10.12
[31c24e10] Distributions v0.25.131
[ffbed154] DocStringExtensions v0.9.5
[4e289a0a] EnumX v1.0.7
⌅ [86b6b26d] Evolutionary v0.11.1
[e2ba6199] ExprTools v0.1.11
[55351af7] ExproniconLite v0.10.14
[c87230d0] FFMPEG v0.4.5
[9aa1b823] FastClosures v0.3.2
[1a297f60] FillArrays v1.17.0
[6a86dc24] FiniteDiff v2.33.0
⌅ [53c48c17] FixedPointNumbers v0.8.6
[1fa38f19] Format v1.3.7
[f6369f11] ForwardDiff v1.4.6
[069b7b12] FunctionWrappers v1.1.3
[77dc65aa] FunctionWrappersWrappers v1.13.0
[d9f16b24] Functors v0.5.3
[46192b85] GPUArraysCore v0.2.0
[28b8d3ca] GR v0.73.27
[a0844989] Gamma v1.2.0
⌅ [eafb193a] Highlights v0.5.3
[34004b35] HypergeometricFunctions v0.3.30
[3587e190] InverseFunctions v0.1.17
[92d709cd] IrrationalConstants v0.2.6
[82899510] IteratorInterfaceExtensions v1.0.0
[1019f520] JLFzf v0.1.11
[692b3bcd] JLLWrappers v1.8.0
⌅ [358108f5] JMcDM v0.7.24
⌅ [682c06a0] JSON v0.21.4
[0f8b85d8] JSON3 v1.14.3
[ae98c720] Jieko v0.2.1
[ba0b0d4f] Krylov v0.10.10
[40e66cde] LDLFactorizations v0.10.2
[b964fa9f] LaTeXStrings v1.4.1
[23fbe1c1] Latexify v0.16.12
[1d6d02ad] LeftChildRightSiblingTrees v0.3.0
⌃ [d3d80556] LineSearches v7.5.1
[5c8ed15e] LinearOperators v2.14.3
[2ab3a3ac] LogExpFunctions v1.0.1
[e6f89c97] LoggingExtras v1.2.0
[1914dd2f] MacroTools v0.5.16
[b8f27783] MathOptInterface v1.53.0
[442fdcdd] Measures v0.3.3
[c03570c3] Memoize v0.4.4
[bcdb8e00] Metaheuristics v3.5.0
[0b3b1443] MicroMamba v0.1.15
[e1d29d7a] Missings v1.2.0
[2e0e35c7] Moshi v0.3.12
[ffc61752] Mustache v1.0.21
[d8a4904e] MutableArithmetics v1.8.0
⌅ [d41bc354] NLSolversBase v7.10.0
[76087f3c] NLopt v1.2.1
⌅ [02130f1c] NOMAD v2.4.2
[77ba4419] NaNMath v1.1.4
[6fe1bfb0] OffsetArrays v1.17.0
⌅ [429524aa] Optim v1.13.3
[3bd65402] Optimisers v0.4.9
⌃ [7f7a1694] Optimization v5.4.0
⌃ [3e6eede4] OptimizationBBO v0.4.5
⌅ [bca83a33] OptimizationBase v4.2.0
⌃ [cb963754] OptimizationEvolutionary v0.4.6
⌃ [3aafef2f] OptimizationMetaheuristics v0.3.4
⌃ [4e6fcdb7] OptimizationNLopt v0.3.8
⌃ [2cab0595] OptimizationNOMAD v0.3.4
⌃ [36348300] OptimizationOptimJL v0.4.8
⌃ [42dfb2eb] OptimizationOptimisers v0.3.15
⌃ [72f8369c] OptimizationPRIMA v0.3.4
⌃ [fb0822aa] OptimizationPyCMA v1.2.0
⌃ [cce07bd8] OptimizationSciPy v0.4.5
[bac558e1] OrderedCollections v2.0.1
[90014a1f] PDMats v0.11.41
[0a7d04aa] PRIMA v0.2.4
⌅ [69de0a69] Parsers v2.8.8
[fa939f87] Pidfile v1.3.0
[ccf2f8ad] PlotThemes v3.3.0
[995b91a9] PlotUtils v1.5.0
[91a5bcdd] Plots v1.41.7
[85a6dd25] PositiveFactorizations v0.2.4
[d236fae5] PreallocationTools v1.7.1
[aea7be01] PrecompileTools v1.3.4
[21216c6a] Preferences v1.6.0
[33c8b6b6] ProgressLogging v0.1.6
[92933f4c] ProgressMeter v1.11.0
[43287f4e] PtrArrays v1.4.0
[6099a3de] PythonCall v0.9.36
[10f199a5] QPSReader v0.2.1
[1fd47b50] QuadGK v2.11.3
[3cdcf5f2] RecipesBase v1.3.4
[01d81517] RecipesPipeline v0.6.12
⌅ [731186ca] RecursiveArrayTools v3.54.0
[189a3867] Reexport v1.2.2
[05181044] RelocatableFolders v1.0.1
[ae029012] Requires v1.3.1
[79098fc4] Rmath v0.9.0
[f2b01f46] Roots v3.0.8
[7e49a35a] RuntimeGeneratedFunctions v0.5.26
⌅ [0bca4576] SciMLBase v2.155.2
[31c91b34] SciMLBenchmarks v0.2.1 [loaded: `/home/crackauc/github-runners/amdci3-1/_work/SciMLBenchmarks.jl/SciMLBenchmarks.jl/src/SciMLBenchmarks.jl` (v0.2.1) expected `/home/crackauc/.julia/packages/SciMLBenchmarks/ceJyd/src/SciMLBenchmarks.jl` (v0.2.1)]
⌅ [a6db7da4] SciMLLogging v1.10.1
[c0aeaf25] SciMLOperators v1.30.1
[431bcebd] SciMLPublic v1.3.0
[53ae85a6] SciMLStructures v1.10.5
[6c6a2e73] Scratch v1.3.0
[eb7571c6] SearchSpaces v0.2.0
[efcf1570] Setfield v1.1.2
[992d4aef] Showoff v1.1.1
[66db9d55] SnoopPrecompile v1.0.3
[a2af1166] SortingAlgorithms v1.2.3
[9f842d2f] SparseConnectivityTracer v1.2.3
[0a514795] SparseMatrixColorings v0.4.28
[276daf66] SpecialFunctions v2.9.0
[cae243ae] StackViews v0.1.2
[90137ffa] StaticArrays v1.9.22
[1e83bf80] StaticArraysCore v1.4.4
[10745b16] Statistics v1.11.5
[82ae8749] StatsAPI v1.8.0
[2913bbd2] StatsBase v0.34.13
[4c63d2b9] StatsFuns v2.2.1
[69024149] StringEncodings v0.3.7
[856f2bd8] StructTypes v1.11.0
[2efcf032] SymbolicIndexingInterface v0.3.55
[3783bdb8] TableTraits v1.0.1
[bd369af6] Tables v1.14.0
[62fd8b95] TensorCore v0.1.1
[5d786b92] TerminalLoggers v0.1.8
⌅ [a759f4b9] TimerOutputs v0.5.29
[3bb67fe8] TranscodingStreams v0.11.3
[6dd1b50a] Tulip v0.9.8
⌅ [c3b1956e] TypeUtils v1.14.0
[3a884ed6] UnPack v1.0.2
[1cfade01] UnicodeFun v0.4.1
[e17b2a0c] UnsafePointers v1.0.0
[41fe7b60] Unzip v0.2.0
[44d3d7a6] Weave v0.10.12
[ddb6d928] YAML v0.4.17
[6e34b625] Bzip2_jll v1.0.9+0
[83423d85] Cairo_jll v1.18.7+0
[ee1fde0b] Dbus_jll v1.16.2+0
[2702e6a9] EpollShim_jll v0.0.20230411+1
[2e619515] Expat_jll v2.8.4+0
⌅ [b22a6f82] FFMPEG_jll v8.1.2+0
[a3f928ae] Fontconfig_jll v2.17.1+0
[d7e528f0] FreeType2_jll v2.14.3+1
[559328eb] FriBidi_jll v1.0.17+0
[0656b61e] GLFW_jll v3.5.1+0
[d2c73de3] GR_jll v0.73.27+0
⌅ [b0724c58] GettextRuntime_jll v0.22.4+0
[61579ee1] Ghostscript_jll v9.55.1+0
[7746bdde] Glib_jll v2.88.3+0
[3b182d85] Graphite2_jll v1.3.16+0
[2e76f6c2] HarfBuzz_jll v100.14004.0+0
[aacddb02] JpegTurbo_jll v3.2.0+1
[c1c5ebd0] LAME_jll v3.100.3+0
[88015f11] LERC_jll v4.2.0+0
[1d63c593] LLVMOpenMP_jll v23.1.1+0
⌅ [e9f186c6] Libffi_jll v3.4.7+0
[7e76a0d4] Libglvnd_jll v1.7.1+1
[94ce4f54] Libiconv_jll v1.18.0+0
[4b2f31a3] Libmount_jll v2.42.0+0
[89763e89] Libtiff_jll v4.7.3+0
[38a345b3] Libuuid_jll v2.42.0+0
[079eb43e] NLopt_jll v2.11.0+0
⌅ [2fc7fd02] NOMAD_jll v4.3.1+0
[e7412a2a] Ogg_jll v1.3.6+0
[efe28fd5] OpenSpecFun_jll v0.5.6+0
[91d4177d] Opus_jll v1.6.1+0
[eead6e0c] PRIMA_jll v0.7.1+0
[36c8627f] Pango_jll v1.58.2+0
[30392449] Pixman_jll v0.46.4+0
[c0090381] Qt6Base_jll v6.10.2+2
[629bc702] Qt6Declarative_jll v6.10.2+2
[ce943373] Qt6ShaderTools_jll v6.10.2+1
[6de9746b] Qt6Svg_jll v6.10.2+0
[e99dba38] Qt6Wayland_jll v6.10.2+1
[f50d1b31] Rmath_jll v0.5.2+0
[a44049a8] Vulkan_Loader_jll v1.3.243+0
[a2964d1f] Wayland_jll v1.24.0+0
[ffd25f8a] XZ_jll v5.8.4+0
[f67eecfb] Xorg_libICE_jll v1.1.2+0
[c834827a] Xorg_libSM_jll v1.2.6+0
[4f6342f7] Xorg_libX11_jll v1.8.13+0
[0c0b7dd1] Xorg_libXau_jll v1.0.13+0
[935fb764] Xorg_libXcursor_jll v1.2.4+0
[a3789734] Xorg_libXdmcp_jll v1.1.6+0
[1082639a] Xorg_libXext_jll v1.3.8+0
[d091e8ba] Xorg_libXfixes_jll v6.0.2+0
[a51aa0fd] Xorg_libXi_jll v1.8.4+0
[d1454406] Xorg_libXinerama_jll v1.1.7+0
[ec84b674] Xorg_libXrandr_jll v1.5.6+0
[ea2f1a96] Xorg_libXrender_jll v0.9.12+0
[a65dc6b1] Xorg_libpciaccess_jll v0.19.0+0
[c7cfdc94] Xorg_libxcb_jll v1.17.1+0
[cc61e674] Xorg_libxkbfile_jll v1.2.0+0
[e920d4aa] Xorg_xcb_util_cursor_jll v0.1.6+0
[12413925] Xorg_xcb_util_image_jll v0.4.1+0
[2def613f] Xorg_xcb_util_jll v0.4.1+0
[975044d2] Xorg_xcb_util_keysyms_jll v0.4.1+0
[0d47668e] Xorg_xcb_util_renderutil_jll v0.3.10+0
[c22f9ab0] Xorg_xcb_util_wm_jll v0.4.2+0
[35661453] Xorg_xkbcomp_jll v1.4.7+0
[33bec58e] Xorg_xkeyboard_config_jll v2.47.0+2
[c5fb5394] Xorg_xtrans_jll v1.6.0+0
[3161d3a3] Zstd_jll v1.5.7+1
[35ca27e7] eudev_jll v3.2.14+0
⌅ [214eeab7] fzf_jll v0.61.1+0
[a4ae2306] libaom_jll v3.14.1+0
[0ac62f75] libass_jll v0.17.5+0
[1183f4f0] libdecor_jll v0.2.2+0
[8e53e030] libdrm_jll v2.4.134+0
[2db6ffa8] libevdev_jll v1.13.4+0
[f638f0a6] libfdk_aac_jll v2.0.4+0
[36db933b] libinput_jll v1.28.1+0
[b53b4c65] libpng_jll v1.6.58+0
[9a156e7d] libva_jll v2.23.0+0
[f27f6e37] libvorbis_jll v1.3.8+0
[f8abcde7] micromamba_jll v2.3.1+0
[009596ad] mtdev_jll v1.1.7+0
[4d7b5844] pixi_jll v0.76.2+0
⌅ [1270edf5] x264_jll v10164.0.1+0
[dfaa095f] x265_jll v4.1.0+0
[d8fb68d0] xkbcommon_jll v1.13.0+0
[0dad84c5] ArgTools v1.1.2
[56f22d72] Artifacts v1.11.0
[2a0f44e3] Base64 v1.11.0
[ade2ca70] Dates v1.11.0
[8ba89e20] Distributed v1.11.0
[f43a241f] Downloads v1.7.0
[7b1f6079] FileWatching v1.11.0
[9fa8497b] Future v1.11.0
[b77e0a4c] InteractiveUtils v1.11.0
[ac6e5ff7] JuliaSyntaxHighlighting v1.12.0
[4af54fe1] LazyArtifacts v1.11.0
[b27032c2] LibCURL v0.6.4
[76f85450] LibGit2 v1.11.0
[8f399da3] Libdl v1.11.0
[37e2e46d] LinearAlgebra v1.12.0
[56ddb016] Logging v1.11.0
[d6f4376e] Markdown v1.11.0
[a63ad114] Mmap v1.11.0
[ca575930] NetworkOptions v1.3.0
[44cfe95a] Pkg v1.12.1
[de0858da] Printf v1.11.0
[3fa0cd96] REPL v1.11.0
[9a3f8284] Random v1.11.0
[ea8e919c] SHA v0.7.0
[9e88b42a] Serialization v1.11.0
[6462fe0b] Sockets v1.11.0
[2f01184e] SparseArrays v1.12.0
[f489334b] StyledStrings v1.11.0
[4607b0f0] SuiteSparse
[fa267f1f] TOML v1.0.3
[a4e569a6] Tar v1.10.0
[8dfed614] Test v1.11.0
[cf7118a7] UUIDs v1.11.0
[4ec0a83e] Unicode v1.11.0
[e66e0078] CompilerSupportLibraries_jll v1.3.1+2
[deac9b47] LibCURL_jll v8.15.0+0
[e37daf67] LibGit2_jll v1.9.0+0
[29816b5a] LibSSH2_jll v1.11.3+1
[14a3606d] MozillaCACerts_jll v2025.11.4
[4536629a] OpenBLAS_jll v0.3.29+0
[05823500] OpenLibm_jll v0.8.7+0
[458c3c95] OpenSSL_jll v3.5.6+0
[efcefdf7] PCRE2_jll v10.44.0+1
[bea87d4a] SuiteSparse_jll v7.8.3+2
[83775a58] Zlib_jll v1.3.1+2
[8e850b90] libblastrampoline_jll v5.15.0+0
[8e850ede] nghttp2_jll v1.64.0+1
[3f19e933] p7zip_jll v17.7.0+0
Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated -m`