Skip to content

Commit ed59f83

Browse files
committed
Merge remote-tracking branch 'origin' into gd/update_ad
2 parents ed3f0f9 + 8b4449e commit ed59f83

File tree

9 files changed

+2375
-50
lines changed

9 files changed

+2375
-50
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
---
2+
title: Brusselator sparse AD benchmarks
3+
author: Guillaume Dalle
4+
---
5+
6+
```julia
7+
using ADTypes
8+
using LinearAlgebra, SparseArrays
9+
using BenchmarkTools, DataFrames
10+
import DifferentiationInterface as DI
11+
using Plots
12+
import SparseDiffTools as SDT
13+
using SparseConnectivityTracer: TracerSparsityDetector
14+
using SparseMatrixColorings: GreedyColoringAlgorithm
15+
using Symbolics: SymbolicsSparsityDetector
16+
using Test
17+
```
18+
19+
## Definitions
20+
21+
```julia
22+
brusselator_f(x, y, t) = (((x - 0.3)^2 + (y - 0.6)^2) <= 0.1^2) * (t >= 1.1) * 5.0
23+
24+
limit(a, N) =
25+
if a == N + 1
26+
1
27+
elseif a == 0
28+
N
29+
else
30+
a
31+
end;
32+
33+
function brusselator_2d!(du, u)
34+
t = 0.0
35+
N = size(u, 1)
36+
xyd = range(0; stop=1, length=N)
37+
p = (3.4, 1.0, 10.0, step(xyd))
38+
A, B, alpha, dx = p
39+
alpha = alpha / dx^2
40+
41+
@inbounds for I in CartesianIndices((N, N))
42+
i, j = Tuple(I)
43+
x, y = xyd[I[1]], xyd[I[2]]
44+
ip1, im1, jp1, jm1 = limit(i + 1, N),
45+
limit(i - 1, N), limit(j + 1, N),
46+
limit(j - 1, N)
47+
du[i, j, 1] =
48+
alpha *
49+
(u[im1, j, 1] + u[ip1, j, 1] + u[i, jp1, 1] + u[i, jm1, 1] - 4u[i, j, 1]) +
50+
B +
51+
u[i, j, 1]^2 * u[i, j, 2] - (A + 1) * u[i, j, 1] + brusselator_f(x, y, t)
52+
du[i, j, 2] =
53+
alpha *
54+
(u[im1, j, 2] + u[ip1, j, 2] + u[i, jp1, 2] + u[i, jm1, 2] - 4u[i, j, 2]) +
55+
A * u[i, j, 1] - u[i, j, 1]^2 * u[i, j, 2]
56+
end
57+
end;
58+
59+
function init_brusselator_2d(N::Integer)
60+
xyd = range(0; stop=1, length=N)
61+
N = length(xyd)
62+
u = zeros(N, N, 2)
63+
for I in CartesianIndices((N, N))
64+
x = xyd[I[1]]
65+
y = xyd[I[2]]
66+
u[I, 1] = 22 * (y * (1 - y))^(3 / 2)
67+
u[I, 2] = 27 * (x * (1 - x))^(3 / 2)
68+
end
69+
return u
70+
end;
71+
```
72+
73+
## Correctness
74+
75+
```julia
76+
x0_32 = init_brusselator_2d(32);
77+
```
78+
79+
### Sparsity detection
80+
81+
```julia
82+
S1 = ADTypes.jacobian_sparsity(
83+
brusselator_2d!, similar(x0_32), x0_32, TracerSparsityDetector()
84+
)
85+
S2 = ADTypes.jacobian_sparsity(
86+
brusselator_2d!, similar(x0_32), x0_32, SymbolicsSparsityDetector()
87+
)
88+
@test S1 == S2
89+
```
90+
91+
### Coloring
92+
93+
```julia
94+
c1 = ADTypes.column_coloring(S1, GreedyColoringAlgorithm())
95+
c2 = SDT.matrix_colors(S1)
96+
@test c1 == c2
97+
```
98+
99+
### Differentiation
100+
101+
```julia
102+
backend = AutoSparse(
103+
AutoForwardDiff();
104+
sparsity_detector=TracerSparsityDetector(),
105+
coloring_algorithm=GreedyColoringAlgorithm(),
106+
);
107+
108+
extras = DI.prepare_jacobian(brusselator_2d!, similar(x0_32), backend, x0_32);
109+
J1 = DI.jacobian!(
110+
brusselator_2d!, similar(x0_32), similar(S1, eltype(x0_32)), backend, x0_32, extras
111+
)
112+
113+
cache = SDT.sparse_jacobian_cache(
114+
backend,
115+
SDT.JacPrototypeSparsityDetection(; jac_prototype=S1),
116+
brusselator_2d!,
117+
similar(x0_32),
118+
x0_32,
119+
);
120+
J2 = SDT.sparse_jacobian!(
121+
similar(S1, eltype(x0_32)), backend, cache, brusselator_2d!, similar(x0_32), x0_32
122+
)
123+
124+
@test J1 == J2
125+
```
126+
127+
## Benchmarks
128+
129+
```julia
130+
N_values = 2 .^ (2:8)
131+
```
132+
133+
### Sparsity detection
134+
135+
```julia
136+
td1, td2 = zeros(length(N_values)), zeros(length(N_values))
137+
for (i, N) in enumerate(N_values)
138+
@info "Benchmarking sparsity detection: N=$N"
139+
x0 = init_brusselator_2d(N)
140+
td1[i] = @belapsed ADTypes.jacobian_sparsity(
141+
$brusselator_2d!, $(similar(x0)), $x0, TracerSparsityDetector()
142+
)
143+
td2[i] = @belapsed ADTypes.jacobian_sparsity(
144+
$brusselator_2d!, $(similar(x0)), $x0, SymbolicsSparsityDetector()
145+
)
146+
end
147+
148+
pld = plot(;
149+
title="Sparsity detection on the Brusselator",
150+
xlabel="Input size N",
151+
ylabel="Runtime [s]",
152+
)
153+
plot!(
154+
pld,
155+
N_values,
156+
td1;
157+
lw=2,
158+
linestyle=:auto,
159+
markershape=:auto,
160+
label="SparseConnectivityTracer",
161+
)
162+
plot!(pld, N_values, td2; lw=2, linestyle=:auto, markershape=:auto, label="Symbolics")
163+
plot!(pld; xscale=:log10, yscale=:log10, legend=:topleft, minorgrid=true)
164+
pld
165+
```
166+
167+
### Coloring
168+
169+
```julia
170+
tc1, tc2 = zeros(length(N_values)), zeros(length(N_values))
171+
for (i, N) in enumerate(N_values)
172+
@info "Benchmarking coloring: N=$N"
173+
x0 = init_brusselator_2d(N)
174+
S = ADTypes.jacobian_sparsity(
175+
brusselator_2d!, similar(x0), x0, TracerSparsityDetector()
176+
)
177+
tc1[i] = @belapsed ADTypes.column_coloring($S, GreedyColoringAlgorithm())
178+
tc2[i] = @belapsed SDT.matrix_colors($S)
179+
end
180+
181+
plc = plot(;
182+
title="Coloring on the Brusselator", xlabel="Input size N", ylabel="Runtime [s]"
183+
)
184+
plot!(
185+
plc,
186+
N_values,
187+
tc1;
188+
lw=2,
189+
linestyle=:auto,
190+
markershape=:auto,
191+
label="SparseMatrixColorings",
192+
)
193+
plot!(plc, N_values, tc2; lw=2, linestyle=:auto, markershape=:auto, label="SparseDiffTools")
194+
plot!(plc; xscale=:log10, yscale=:log10, legend=:topleft, minorgrid=true)
195+
plc
196+
```
197+
198+
### Differentiation
199+
200+
```julia
201+
tj1, tj2 = zeros(length(N_values)), zeros(length(N_values))
202+
for (i, N) in enumerate(N_values)
203+
@info "Benchmarking differentiation: N=$N"
204+
x0 = init_brusselator_2d(N)
205+
S = ADTypes.jacobian_sparsity(
206+
brusselator_2d!, similar(x0), x0, TracerSparsityDetector()
207+
)
208+
J = similar(S, eltype(x0))
209+
210+
tj1[i] = @belapsed DI.jacobian!($brusselator_2d!, _y, _J, $backend, $x0, _extras) setup = (
211+
_y = similar($x0);
212+
_J = similar($J);
213+
_extras = DI.prepare_jacobian($brusselator_2d!, similar($x0), $backend, $x0)
214+
) evals = 1
215+
216+
tj2[i] = @belapsed SDT.sparse_jacobian!(_J, $backend, _cache, $brusselator_2d!, _y, $x0) setup = (
217+
_y = similar($x0);
218+
_J = similar($J);
219+
_cache = SDT.sparse_jacobian_cache(
220+
$backend,
221+
SDT.JacPrototypeSparsityDetection(; jac_prototype=$S),
222+
$brusselator_2d!,
223+
similar($x0),
224+
$x0,
225+
)
226+
) evals = 1
227+
end
228+
229+
plj = plot(;
230+
title="Sparse Jacobian on the Brusselator", xlabel="Input size N", ylabel="Runtime [s]"
231+
)
232+
plot!(
233+
plj,
234+
N_values,
235+
tj1;
236+
lw=2,
237+
linestyle=:auto,
238+
markershape=:auto,
239+
label="DifferentiationInterface",
240+
)
241+
plot!(plj, N_values, tj2; lw=2, linestyle=:auto, markershape=:auto, label="SparseDiffTools")
242+
plot!(plj; xscale=:log10, yscale=:log10, legend=:topleft, minorgrid=true)
243+
plj
244+
```
245+
246+
### Summary
247+
248+
```julia
249+
pl = plot(;
250+
title="Is the new pipeline worth it?\nTest case: Brusselator",
251+
xlabel="Input size N",
252+
ylabel="Runtime ratio DI / SparseDiffTools",
253+
)
254+
plot!(
255+
pl,
256+
N_values,
257+
td2 ./ td1;
258+
lw=2,
259+
linestyle=:auto,
260+
markershape=:auto,
261+
label="sparsity detection speedup",
262+
)
263+
plot!(
264+
pl,
265+
N_values,
266+
tc2 ./ tc1;
267+
lw=2,
268+
linestyle=:auto,
269+
markershape=:auto,
270+
label="coloring speedup",
271+
)
272+
plot!(
273+
pl,
274+
N_values,
275+
tj2 ./ tj1;
276+
lw=2,
277+
linestyle=:auto,
278+
markershape=:auto,
279+
label="differentiation speedup",
280+
)
281+
plot!(pl, N_values, ones(length(N_values)); lw=3, color=:black, label="same speed")
282+
plot!(pl; xscale=:log10, yscale=:log10, minorgrid=true, legend=:right)
283+
pl
284+
```

0 commit comments

Comments
 (0)