1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate;
use ;
/// Runs before every measured sample of a set's candidates, so a candidate whose operands fit
/// the device's last-level cache is timed reading memory the way a real call does.
///
/// A tuner samples one candidate several times over the same inputs, and a warm-up runs
/// first: from the second launch on, an operand small enough for the cache is served from it.
/// A memory-bound kernel then reads as several times faster than the bus, the round's
/// throughput bound is met by the first candidate tried, and the round ends there — with a
/// winner chosen on a read production never gets. The set says how to evict, since it knows
/// what its operands weigh; the tuner says when.
///
/// What the eviction runs is the set's business — typically a launch that writes past the
/// cache's capacity through the inputs' client. It receives the reference inputs the tune was
/// called with rather than the generated ones the candidates are measured on, so it can scrub
/// through buffers the caller already holds instead of allocating its own: an output the
/// winner overwrites afterwards is scratch until then. Whether that reaches past the cache is
/// the set's call — an operand-sized write evicts an operand-sized cache, no more.
///
/// The eviction is issued outside the profiled region, so it costs the round time rather than
/// the sample, as long as it goes through the stream the sample is profiled on: the tuner
/// orders nothing between the two, and a launch on another stream can overlap the sample or
/// land after it.
///
/// A failed eviction is logged and the sample is measured anyway, warm: an eviction is a
/// measurement aid, and losing one is not worth failing the tune for.
/// `Fn(&K, &A) -> Result<(), E>` acts as an [`Eviction`] when `A` is an owned type. For
/// multi-input kernels, `A` is a tuple that the closure destructures internally.
/// An [`Eviction`] bound to one key and the reference inputs of one tune: what a benchmark
/// loop calls before each sample.
///
/// `FnMut` rather than `Fn` because the loop lends it out exclusively: the closure holds the
/// inputs, which are only `Send`, and a shared borrow would need them `Sync` to reach the
/// device thread the samples are launched from.
pub type Evictor<'i> = dyn FnMut + Send + 'i;