Skip to content

Commit 5267820

Browse files
authored
Add option to force warmup (or no warmup) (#177)
* Add warmup option * Test save every result when warmup=false (and evals=1) * Update docs, and precompilation, add tests
1 parent 3c86e3c commit 5267820

File tree

5 files changed

+69
-14
lines changed

5 files changed

+69
-14
lines changed

src/benchmarking.jl

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ function benchmark(init, setup, fs::Tuple{Vararg{Any, N}}, teardown;
1313
evals::Union{Int, Nothing}=nothing,
1414
samples::Union{Int, Nothing}=nothing,
1515
seconds::Union{Real, Nothing}=(samples===nothing ? DEFAULTS.seconds : 10*DEFAULTS.seconds)*N,
16-
gc::Bool=DEFAULTS.gc) where N
17-
_benchmark_1(init, setup, teardown, evals, samples, seconds, gc, fs...)
16+
gc::Bool=DEFAULTS.gc,
17+
warmup::Union{Bool, Nothing}=nothing) where N
18+
_benchmark_1(init, setup, teardown, evals, samples, seconds, gc, warmup, fs...)
1819
end
19-
_benchmark_1(init, setup, teardown, evals::Union{Int, Nothing}, samples::Union{Int, Nothing}, seconds::Real, gc::Bool, fs...) =
20-
_benchmark_1(init, setup, teardown, evals, samples, Float64(seconds), gc, fs...)
21-
function _benchmark_1(init, setup, teardown, evals::Union{Int, Nothing}, samples::Union{Int, Nothing}, seconds::Union{Float64, Nothing}, gc::Bool, fs...)
20+
_benchmark_1(init, setup, teardown, evals::Union{Int, Nothing}, samples::Union{Int, Nothing}, seconds::Real, gc::Bool, warmup::Union{Bool, Nothing}, fs...) =
21+
_benchmark_1(init, setup, teardown, evals, samples, Float64(seconds), gc, warmup, fs...)
22+
function _benchmark_1(init, setup, teardown, evals::Union{Int, Nothing}, samples::Union{Int, Nothing}, seconds::Union{Float64, Nothing}, gc::Bool, warmup::Union{Bool, Nothing}, fs...)
2223
@nospecialize
2324
N = length(fs)
2425

@@ -37,16 +38,24 @@ function _benchmark_1(init, setup, teardown, evals::Union{Int, Nothing}, samples
3738

3839
samples == 0 && return ntuple(i -> Benchmark([_benchmark_2(args1, setup, teardown, gc, evals, false, fs...)[1][i]]), N)
3940

40-
warmup, start_time = _benchmark_2(args1, setup, teardown, gc, 1, false, fs...)
41+
warmup_result, start_time = if warmup === false
42+
if seconds == 0
43+
_benchmark_2(args1, setup, teardown, gc, 1, true, fs...)
44+
else
45+
(nothing, time_ns())
46+
end
47+
else
48+
_benchmark_2(args1, setup, teardown, gc, 1, false, fs...)
49+
end
4150

42-
seconds == 0 && return ntuple(i -> Benchmark([warmup[i]]), N)
51+
seconds == 0 && return ntuple(i -> Benchmark([warmup_result[i]]), N)
4352
new_evals = if evals === nothing
4453
@assert evals === samples === nothing && seconds !== nothing
4554

46-
if sum(w.time for w in warmup) > 2seconds && all(w.compile_fraction < .5 for w in warmup)
55+
if warmup === nothing && sum(w.time for w in warmup_result) > 2seconds && all(w.compile_fraction < .5 for w in warmup_result)
4756
# The estimated runtime in the warmup already exceeds the time budget.
4857
# Return the warmup result (which is marked as not having a warmup).
49-
return ntuple(i -> Benchmark([warmup[i]]), N)
58+
return ntuple(i -> Benchmark([warmup_result[i]]), N)
5059
end
5160

5261
calibration1, time = _benchmark_2(args1, setup, teardown, gc, 1, true, fs...)

src/precompile.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ precompile(create_function, (Symbol,))
44
precompile(create_first_function, (Symbol,))
55
precompile(create_function, (Expr,))
66
precompile(create_first_function, (Expr,))
7-
precompile(_benchmark_1, (Any,Any,Any,Int,Int,Float64,Bool,Any))
7+
precompile(_benchmark_1, (Any,Any,Any,Int,Int,Float64,Bool,Nothing,Any))
88
precompile(Base.show, (IO, MIME"text/plain", Sample))

src/public.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ arguments to ordinary functions. Keyword arguments to control executions are
113113
the benchmark. As an experimental option, this may be removed in the future or its
114114
semantics may change. This option also depends on Julia internals and so it may break in
115115
future versions of Julia.
116+
- `warmup::Union{Nothing, Bool}` An experimental option to force warmups to run or not
117+
run. With `warmup = true` we always run a warmup. With `warmup = false` we assume a
118+
warmup has already been run and both skip a warmup and nevertheless report the first
119+
sample as already having been warmed up. With `warmup=nothing` (the default) we almost
120+
always run a warmup but will skip it if the estimated runtime of the warmup exceeds
121+
twice the runtime budget and less than half of the warmup time is spent compiling. As
122+
an experimental option, this may be removed in the future or its semantics may change.
123+
The heuristic for choosing when to automatically skip the warmup may also change in
124+
future versions of Chairmarks.
116125
117126
# Interpolation
118127
@@ -247,10 +256,10 @@ A global constant that holds default benchmarking parameters.
247256
When a parameter is unspecified it defaults to the value stored in `Chairmarks.DEFAULTS`.
248257
249258
Currently there is one stable default: `Chairmarks.DEFAULTS.seconds::Float64` which defaults
250-
to 0.1; and one experimental default: `Chairmarks.DEFAULTS.gc::Bool` which defaults to
251-
`true`.
259+
to 0.1; and two experimental defaults: `Chairmarks.DEFAULTS.gc::Bool` which defaults to
260+
`true`, and `Chairmarks.DEFAULTS.warmup::Union{Bool, Nothing}` which defaults to `nothing`.
252261
253262
All default values may be changed in the future and the `gc` default may be removed
254263
entirely.
255264
"""
256-
const DEFAULTS = Defaults(0.1, true)
265+
const DEFAULTS = Defaults(0.1, true, nothing)

src/types.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,5 @@ The type of [`Chairmarks.DEFAULTS`](@ref)
8484
mutable struct Defaults
8585
seconds::Float64
8686
gc::Bool
87+
warmup::Union{Bool, Nothing}
8788
end

test/runtests.jl

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ else
181181
@test GC.enable(true)
182182
end
183183

184-
@testset "no warmup" begin
184+
@testset "no warmup heuristics" begin
185185
no_warmup_counter = Ref(0)
186186
res = @be begin no_warmup_counter[] += 1; sleep(.1) end seconds=.05
187187
@test no_warmup_counter[] == 1
@@ -192,6 +192,42 @@ else
192192
@test occursin("without a warmup", sprint(show, MIME"text/plain"(), res))
193193
end
194194

195+
@testset "no warmup parameter" begin
196+
counter = Ref(0)
197+
res = @be begin counter[] += 1; sleep(.1) end seconds=.05 warmup=true
198+
@test counter[] == 2
199+
sample = only(res.samples) # qualify only for compat
200+
@test .1 < sample.time
201+
@test sample.warmup == 1
202+
@test !occursin("without a warmup", sprint(show, MIME"text/plain"(), sample))
203+
@test !occursin("without a warmup", sprint(show, MIME"text/plain"(), res))
204+
205+
counter[] = 0
206+
res = @be begin counter[] += 1; sleep(.1) end seconds=.05 warmup=false
207+
@test counter[] == 1
208+
sample = only(res.samples) # qualify only for compat
209+
@test .1 < sample.time
210+
@test sample.warmup == 1
211+
@test !occursin("without a warmup", sprint(show, MIME"text/plain"(), sample))
212+
@test !occursin("without a warmup", sprint(show, MIME"text/plain"(), res))
213+
214+
counter[] = 0
215+
res = @be begin counter[] += 1; sleep(.001) end seconds=.05 warmup=false
216+
# @test counter[] > 1 This would be flaky
217+
@test .001 < minimum(res).time
218+
@test 1 == only(unique(s.evals for s in res.samples))
219+
@test all(s -> s.warmup == 1, res.samples)
220+
@test length(res.samples) == counter[] # Save and return every sample
221+
222+
counter[] = 0
223+
res = @be begin counter[] += 1; sleep(.001) end seconds=0 warmup=false # warmup=false and seconds=0 is a notable edge case.
224+
@test counter[] == 1
225+
sample = only(res.samples) # qualify only for compat
226+
@test sample.evals == 1
227+
@test .001 < sample.time
228+
@test sample.warmup == 1
229+
end
230+
195231
@testset "writefixed" begin
196232
@test Chairmarks.writefixed(-1.23045, 4) == "-1.2305"
197233
@test Chairmarks.writefixed(-1.23045, 3) == "-1.230"

0 commit comments

Comments
 (0)