@@ -8,7 +8,7 @@ Pkg.activate(joinpath(@__DIR__, ".."))
88## Load Dependencies
99
1010```julia
11- using BenchmarkTools, ComplementaritySolve, DataFrames, PyPlot, StableRNGs
11+ using BenchmarkTools, ComplementaritySolve, DataFrames, NonlinearSolve, PyPlot, StableRNGs
1212```
1313
1414## Basic LCP
@@ -27,11 +27,13 @@ SOLVERS = [BokhovenIterativeAlgorithm(),
2727 RPGS(),
2828 InteriorPointMethod(),
2929 NonlinearReformulation(),
30+ NonlinearReformulation(:smooth, Broyden(; batched=true)),
3031]
3132times = zeros(length(SOLVERS), 2)
32- solvers = ["Bok.", "RPSOR", "PGS", "RPGS", "IPM", "NLR"]
33+ solvers = ["Bok.", "RPSOR", "PGS", "RPGS", "IPM", "NLR (Newton)", "NLR (Broyden) "]
3334
3435for (i, solver) in enumerate(SOLVERS)
36+ @info "Benchmarking $(solvers[i])"
3537 prob_iip = LCP{true}(A₁, q₁, rand(StableRNG(0), 2))
3638 prob_oop = LCP{false}(A₁, q₁, rand(StableRNG(0), 2))
3739 times[i, 1] = @belapsed solve($prob_iip, $solver)
4042```
4143
4244```julia
43- xloc = 1:length(solvers)
44- width = 0.4 # the width of the bars
45- multiplier = 0
46- fig, ax = subplots(layout="constrained")
47- ax.set_yscale("log")
48-
49- for (i, group) in enumerate(["Inplace", "Out of Place"])
50- global multiplier
51- offset = width * multiplier
52- rects = ax.bar(xloc .+ offset, times[:, i], width, label=group)
53- for (j, rect) in enumerate(rects)
54- height = rect.get_height()
55- ax.annotate("$(round(times[j, i] * 10^6; digits=2))μs",
56- xy=(rect.get_x() + rect.get_width() / 2, height),
57- xytext=(0, 3), # 3 points vertical offset
58- textcoords="offset points",
59- ha="center", va="bottom")
45+ let _=plt.xkcd()
46+ xloc = 1:length(solvers)
47+ width = 0.4 # the width of the bars
48+ multiplier = 0
49+ fig, ax = subplots(layout="constrained", figsize=(14, 6))
50+ ax.set_yscale("log")
51+
52+ for (i, group) in enumerate(["Inplace", "Out of Place"])
53+ offset = width * multiplier
54+ rects = ax.bar(xloc .+ offset, times[:, i], width, label=group)
55+ for (j, rect) in enumerate(rects)
56+ height = rect.get_height()
57+ ax.annotate("$(round(times[j, i] * 10^6; digits=2))μs",
58+ xy=(rect.get_x() + rect.get_width() / 2, height),
59+ xytext=(0, 3), # 3 points vertical offset
60+ textcoords="offset points",
61+ ha="center", va="bottom")
62+ end
63+ multiplier += 1
6064 end
61- multiplier += 1
62- end
6365
64- ax.set_ylabel("Times (s)")
65- ax.set_title("Basic LCP Unbatched")
66- ax.set_xticks(xloc .+ width ./ 2, solvers)
67- ax.legend(loc="upper right", ncols=3)
68- fig.tight_layout()
69- fig
66+ ax.set_ylabel("Times (s)")
67+ ax.set_title("Basic LCP Unbatched")
68+ ax.set_xticks(xloc .+ width ./ 2, solvers)
69+ ax.legend(ncols=3)
70+ fig.tight_layout()
71+ fig
72+ end
7073```
7174
7275### Batched Version
@@ -81,51 +84,63 @@ SOLVERS = [BokhovenIterativeAlgorithm(),
8184 PGS(),
8285 RPGS(),
8386 InteriorPointMethod(),
84- NonlinearReformulation(),
87+ NonlinearReformulation(:smooth, SimpleNewtonRaphson(; batched=true)),
88+ NonlinearReformulation(:smooth, SimpleDFSane(; batched=true)),
89+ NonlinearReformulation(:smooth, Broyden(; batched=true)),
8590]
86- BATCH_SIZES = 2 .^ 1:2:11
91+ BATCH_SIZES = 2 .^ ( 1:2:11)
8792times = zeros(length(SOLVERS), length(BATCH_SIZES), 2)
88- solvers = ["Bok.", "RPSOR", "PGS", "RPGS", "IPM", "NLR"]
93+ solvers = ["Bok.", "RPSOR", "PGS", "RPGS", "IPM", "NLR (Newton)", "NLR (DFSane)", "NLR (Broyden) "]
8994
9095for (i, solver) in enumerate(SOLVERS)
96+ @info "Benchmarking $(solvers[i])"
9197 for (j, N) in enumerate(BATCH_SIZES)
9298 prob_iip = LCP{true}(A₁, q₁, rand(StableRNG(0), 2, N))
9399 prob_oop = LCP{false}(A₁, q₁, rand(StableRNG(0), 2, N))
94- times[i, j, 1] = @elapsed solve(prob_iip, solver)
95- times[i, j, 2] = @elapsed solve(prob_oop, solver)
100+ times[i, j, 2] = @belapsed solve($prob_oop, $solver)
101+ if i == 6
102+ times[i, j, 1] = -1 # SimpleNewtonRaphson is not implemented for inplace
103+ continue
104+ end
105+ times[i, j, 1] = @belapsed solve($prob_iip, $solver)
96106 end
97107end
98108```
99109
100-
101110```julia
102- xloc = 1:length(solvers)
103- width = 0.4 # the width of the bars
104- multiplier = 0
105- fig, ax = subplots(layout="constrained")
106- ax.set_yscale("log")
107-
108- for (i, group) in enumerate(["Inplace", "Out of Place"])
109- global multiplier
110- offset = width * multiplier
111- rects = ax.bar(xloc .+ offset, times[:, i], width, label=group)
112- for (j, rect) in enumerate(rects)
113- height = rect.get_height()
114- ax.annotate("$(round(times[j, i] * 10^6; digits=2))μs",
115- xy=(rect.get_x() + rect.get_width() / 2, height),
116- xytext=(0, 3), # 3 points vertical offset
117- textcoords="offset points",
118- ha="center", va="bottom")
111+ let _=plt.xkcd()
112+ prop_cycle = plt.rcParams["axes.prop_cycle"]
113+ colors = prop_cycle.by_key()["color"]
114+ fig, (ax1, ax2) = subplots(1, 2; layout="constrained", sharey=true, sharex=true, figsize=(16, 6))
115+ ax1.set_yscale("log")
116+ ax1.set_xscale("log")
117+
118+ fig.suptitle("Basic LCP Batched")
119+ ax1.set_title("In-Place Solvers")
120+ ax2.set_title("Out-Of-Place Solvers")
121+
122+ for (j, solver) in enumerate(solvers)
123+ if !any(times[j, :, 1] .< 0)
124+ ax1.plot(BATCH_SIZES, times[j, :, 1]; label=solver, color=colors[j])
125+ ax1.scatter(BATCH_SIZES, times[j, :, 1]; color=colors[j])
126+ end
127+ if !any(times[j, :, 2] .< 0)
128+ ax2.plot(BATCH_SIZES, times[j, :, 2]; label=solver, color=colors[j])
129+ ax2.scatter(BATCH_SIZES, times[j, :, 2]; color=colors[j])
130+ end
119131 end
120- multiplier += 1
121- end
122132
123- ax.set_ylabel("Times (s)")
124- ax.set_title("Basic LCP Unbatched")
125- ax.set_xticks(xloc .+ width ./ 2, solvers)
126- ax.legend(loc="upper right", ncols=3)
127- fig.tight_layout()
128- fig
133+ ax1.set_ylabel("Times (s)")
134+ ax1.set_xlabel("Batch Size")
135+ ax2.set_xlabel("Batch Size")
136+ ax1.legend(ncols=3)
137+ ax2.legend(ncols=3)
138+ fig.tight_layout()
139+ fig
140+ end
129141```
130142
131-
143+ ```julia, echo = false
144+ import SciMLBenchmarks
145+ SciMLBenchmarks.bench_footer(@__DIR__, @__FILE__)
146+ ```
0 commit comments