Skip to content

Commit f765b40

Browse files
authored
Make benchmarks not depend on TuringBenchmarking.jl, and run ]dev .. (#834)
* Make benchmarks not depend on TuringBenchmarking.jl * Make benchmarks.jl dev the local DDPPL version * Add benchmarks compat bounds * Use ForwardDiff with dynamic benchmark model
1 parent d39a9d6 commit f765b40

File tree

4 files changed

+81
-29
lines changed

4 files changed

+81
-29
lines changed

benchmarks/Project.toml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,22 @@ uuid = "d94a1522-c11e-44a7-981a-42bf5dc1a001"
33
version = "0.1.0"
44

55
[deps]
6+
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
67
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
78
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
89
DynamicPPL = "366bfd00-2699-11ea-058f-f148b4cae6d8"
10+
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
911
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
12+
LogDensityProblems = "6fdf6af0-433a-55f7-b3ed-c6c6e0b8df7c"
1013
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
11-
TuringBenchmarking = "0db1332d-5c25-4deb-809f-459bc696f94f"
14+
ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267"
15+
16+
[compat]
17+
ADTypes = "1.14.0"
18+
BenchmarkTools = "1.6.0"
19+
Distributions = "0.25.117"
20+
# DynamicPPL deliberately has no compat bound, to allow using the local version.
21+
ForwardDiff = "0.10.38"
22+
LogDensityProblems = "2.1.2"
23+
PrettyTables = "2.4.0"
24+
ReverseDiff = "1.15.3"

benchmarks/benchmarks.jl

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
using Pkg
2+
# To ensure we benchmark the local version of DynamicPPL, dev the folder above.
3+
Pkg.develop(; path=joinpath(@__DIR__, ".."))
4+
15
using DynamicPPLBenchmarks: Models, make_suite
26
using BenchmarkTools: @benchmark, median, run
37
using PrettyTables: PrettyTables, ft_printf
@@ -47,7 +51,9 @@ chosen_combinations = [
4751
("Multivariate 1k", multivariate1k, :typed, :reversediff, true),
4852
("Loop univariate 10k", loop_univariate10k, :typed, :reversediff, true),
4953
("Multivariate 10k", multivariate10k, :typed, :reversediff, true),
50-
("Dynamic", Models.dynamic(), :typed, :reversediff, true),
54+
# TODO(mhauru) Would like to use :reversediff here, but see
55+
# https://github.com/TuringLang/DynamicPPL.jl/issues/835
56+
("Dynamic", Models.dynamic(), :typed, :forwarddiff, true),
5157
("Submodel", Models.parent(randn()), :typed, :reversediff, true),
5258
("LDA", lda_instance, :typed, :reversediff, true),
5359
]
@@ -62,22 +68,12 @@ end
6268
results_table = Tuple{String,String,String,Bool,Float64,Float64}[]
6369

6470
for (model_name, model, varinfo_choice, adbackend, islinked) in chosen_combinations
65-
suite = make_suite(model, varinfo_choice, adbackend)
71+
suite = make_suite(model, varinfo_choice, adbackend, islinked)
6672
results = run(suite)
67-
result_key = islinked ? "linked" : "standard"
68-
69-
eval_time = median(results["evaluation"][result_key]).time
73+
eval_time = median(results["evaluation"]).time
7074
relative_eval_time = eval_time / reference_time
71-
72-
grad_group = results["gradient"]
73-
if isempty(grad_group)
74-
relative_ad_eval_time = NaN
75-
else
76-
grad_backend_key = first(keys(grad_group))
77-
ad_eval_time = median(grad_group[grad_backend_key][result_key]).time
78-
relative_ad_eval_time = ad_eval_time / eval_time
79-
end
80-
75+
ad_eval_time = median(results["gradient"]).time
76+
relative_ad_eval_time = ad_eval_time / eval_time
8177
push!(
8278
results_table,
8379
(

benchmarks/src/DynamicPPLBenchmarks.jl

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
11
module DynamicPPLBenchmarks
22

33
using DynamicPPL: VarInfo, SimpleVarInfo, VarName
4-
using BenchmarkTools: BenchmarkGroup
5-
using TuringBenchmarking: make_turing_suite
4+
using BenchmarkTools: BenchmarkGroup, @benchmarkable
5+
using DynamicPPL: DynamicPPL
6+
using ADTypes: ADTypes
7+
using LogDensityProblems: LogDensityProblems
8+
9+
# Load some the default backends to trigger conditional loading.
10+
using ForwardDiff: ForwardDiff
11+
using ReverseDiff: ReverseDiff
612

713
include("./Models.jl")
814
using .Models: Models
915

1016
export Models, make_suite
1117

18+
# Utility functions for representing AD backends using symbols.
19+
# Copied from TuringBenchmarking.jl.
20+
const SYMBOL_TO_BACKEND = Dict(
21+
:forwarddiff => ADTypes.AutoForwardDiff(; chunksize=0),
22+
:reversediff => ADTypes.AutoReverseDiff(; compile=false),
23+
:reversediff_compiled => ADTypes.AutoReverseDiff(; compile=true),
24+
:mooncake => ADTypes.AutoMooncake(; config=nothing),
25+
)
26+
27+
to_backend(x) = error("Unknown backend: $x")
28+
to_backend(x::ADTypes.AbstractADType) = x
29+
function to_backend(x::Union{AbstractString,Symbol})
30+
k = Symbol(lowercase(string(x)))
31+
haskey(SYMBOL_TO_BACKEND, k) || error("Unknown backend: $x")
32+
return SYMBOL_TO_BACKEND[k]
33+
end
34+
1235
"""
13-
make_suite(model, varinfo_choice::Symbol, adbackend::Symbol)
36+
make_suite(model, varinfo_choice::Symbol, adbackend::Symbol, islinked::Bool)
1437
1538
Create a benchmark suite for `model` using the selected varinfo type and AD backend.
1639
Available varinfo choices:
@@ -20,8 +43,10 @@ Available varinfo choices:
2043
• `:simple_dict` → builds a `SimpleVarInfo{Float64}` from a Dict (pre-populated with the model’s outputs)
2144
2245
The AD backend should be specified as a Symbol (e.g. `:forwarddiff`, `:reversediff`, `:zygote`).
46+
47+
`islinked` determines whether to link the VarInfo for evaluation.
2348
"""
24-
function make_suite(model, varinfo_choice::Symbol, adbackend::Symbol)
49+
function make_suite(model, varinfo_choice::Symbol, adbackend::Symbol, islinked::Bool)
2550
suite = BenchmarkGroup()
2651

2752
vi = if varinfo_choice == :untyped
@@ -40,14 +65,32 @@ function make_suite(model, varinfo_choice::Symbol, adbackend::Symbol)
4065
error("Unknown varinfo choice: $varinfo_choice")
4166
end
4267

43-
# Add the AD benchmarking suite.
44-
suite = make_turing_suite(
45-
model;
46-
adbackends=[adbackend],
47-
varinfo=vi,
48-
check_grads=true,
49-
error_on_failed_backend=true,
50-
)
68+
adbackend = to_backend(adbackend)
69+
context = DynamicPPL.DefaultContext()
70+
71+
if islinked
72+
vi = DynamicPPL.link(vi, model)
73+
end
74+
75+
# We construct `LogDensityFunction` using different values
76+
# than the ones we're going to use for the test. Some of the AD backends
77+
# compile the tape upon `LogDensityFunction` construction, and we want to
78+
# evaluate using inputs different from those that the tape was compiled for.
79+
f = DynamicPPL.LogDensityFunction(model, vi, context; adtype=adbackend)
80+
81+
# The parameters at which we evaluate f.
82+
θ = if islinked
83+
randn(length(vi[:]))
84+
else
85+
rand(Vector, model)
86+
end
87+
88+
# Run once to trigger compilation.
89+
LogDensityProblems.logdensity_and_gradient(f, θ)
90+
suite["gradient"] = @benchmarkable $(LogDensityProblems.logdensity_and_gradient)($f, $θ)
91+
92+
# Also benchmark just standard model evaluation because why not.
93+
suite["evaluation"] = @benchmarkable $(DynamicPPL.evaluate!!)($model, $vi, $context)
5194

5295
return suite
5396
end

benchmarks/src/Models.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ using Distributions:
1717
logpdf,
1818
product_distribution,
1919
truncated
20-
using DynamicPPL: @model, to_submodel
20+
using DynamicPPL: DynamicPPL, @model, to_submodel
2121
using LinearAlgebra: cholesky
2222

2323
export simple_assume_observe_non_model,

0 commit comments

Comments
 (0)