@@ -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,9 +27,10 @@ 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)
3536 prob_iip = LCP{true}(A₁, q₁, rand(StableRNG(0), 2))
4041```
4142
4243```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")
44+ let _=plt.xkcd()
45+ xloc = 1:length(solvers)
46+ width = 0.4 # the width of the bars
47+ multiplier = 0
48+ fig, ax = subplots(layout="constrained", figsize=(14, 6))
49+ ax.set_yscale("log")
50+
51+ for (i, group) in enumerate(["Inplace", "Out of Place"])
52+ offset = width * multiplier
53+ rects = ax.bar(xloc .+ offset, times[:, i], width, label=group)
54+ for (j, rect) in enumerate(rects)
55+ height = rect.get_height()
56+ ax.annotate("$(round(times[j, i] * 10^6; digits=2))μs",
57+ xy=(rect.get_x() + rect.get_width() / 2, height),
58+ xytext=(0, 3), # 3 points vertical offset
59+ textcoords="offset points",
60+ ha="center", va="bottom")
61+ end
62+ multiplier += 1
6063 end
61- multiplier += 1
62- end
6364
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
65+ ax.set_ylabel("Times (s)")
66+ ax.set_title("Basic LCP Unbatched")
67+ ax.set_xticks(xloc .+ width ./ 2, solvers)
68+ ax.legend(ncols=3)
69+ fig.tight_layout()
70+ fig
71+ end
7072```
7173
7274### Batched Version
@@ -81,51 +83,59 @@ SOLVERS = [BokhovenIterativeAlgorithm(),
8183 PGS(),
8284 RPGS(),
8385 InteriorPointMethod(),
84- NonlinearReformulation(),
86+ NonlinearReformulation(:smooth, SimpleNewtonRaphson(; batched=true)),
87+ NonlinearReformulation(:smooth, SimpleDFSane(; batched=true)),
88+ NonlinearReformulation(:smooth, Broyden(; batched=true)),
8589]
86- BATCH_SIZES = 2 .^ 1:2:11
90+ BATCH_SIZES = 2 .^ ( 1:2:11)
8791times = zeros(length(SOLVERS), length(BATCH_SIZES), 2)
88- solvers = ["Bok.", "RPSOR", "PGS", "RPGS", "IPM", "NLR"]
92+ solvers = ["Bok.", "RPSOR", "PGS", "RPGS", "IPM", "NLR (Newton)", "NLR (DFSane)", "NLR (Broyden) "]
8993
9094for (i, solver) in enumerate(SOLVERS)
9195 for (j, N) in enumerate(BATCH_SIZES)
9296 prob_iip = LCP{true}(A₁, q₁, rand(StableRNG(0), 2, N))
9397 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)
98+ times[i, j, 2] = @belapsed solve($prob_oop, $solver)
99+ if i == 6
100+ times[i, j, 1] = -1 # SimpleNewtonRaphson is not implemented for inplace
101+ continue
102+ end
103+ times[i, j, 1] = @belapsed solve($prob_iip, $solver)
96104 end
97105end
98106```
99107
100-
101108```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")
109+ let _=plt.xkcd()
110+ prop_cycle = plt.rcParams["axes.prop_cycle"]
111+ colors = prop_cycle.by_key()["color"]
112+ fig, (ax1, ax2) = subplots(1, 2; layout="constrained", sharey=true, sharex=true, figsize=(16, 6))
113+ ax1.set_yscale("log")
114+ ax1.set_xscale("log")
115+
116+ fig.suptitle("Basic LCP Batched")
117+ ax1.set_title("In-Place Solvers")
118+ ax2.set_title("Out-Of-Place Solvers")
119+
120+ for (j, solver) in enumerate(solvers)
121+ if !any(times[j, :, 1] .< 0)
122+ ax1.plot(BATCH_SIZES, times[j, :, 1]; label=solver, color=colors[j])
123+ ax1.scatter(BATCH_SIZES, times[j, :, 1]; color=colors[j])
124+ end
125+ if !any(times[j, :, 2] .< 0)
126+ ax2.plot(BATCH_SIZES, times[j, :, 2]; label=solver, color=colors[j])
127+ ax2.scatter(BATCH_SIZES, times[j, :, 2]; color=colors[j])
128+ end
119129 end
120- multiplier += 1
121- end
122130
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
131+ ax1.set_ylabel("Times (s)")
132+ ax1.set_xlabel("Batch Size")
133+ ax2.set_xlabel("Batch Size")
134+ ax1.legend(ncols=3)
135+ ax2.legend(ncols=3)
136+ fig.tight_layout()
137+ fig
138+ end
129139```
130140
131141
0 commit comments