Skip to main content

cubek_std/microkernel/
estimate.rs

1use cubecl::tune::Work;
2
3/// A kernel's performance, estimated: what the kernel a routine prepared asks of a device,
4/// counted from its own walk, before any device is known.
5///
6/// One vocabulary for every routine of every family, so kernels of different routines are
7/// compared on the same quantities. It starts from the kernel's grid (its `From<&Grid>`), and
8/// each part has one owner, which sets it whole: the problem its [`demand`](Self::demand), the
9/// component placing the stage's reads its [`staging`](Self::staging), the microkernel holding
10/// the work in its units its [`work`](Self::work). A routine sets what it owns and hands the
11/// estimate to its microkernel, which does the same, as the kernel hands down its walk.
12///
13/// Counts only: every rate, latency and capacity is the device's. A part left unset is a routine
14/// that forgot its own.
15#[derive(Debug, Clone, PartialEq)]
16pub struct KernelEstimate {
17    /// Cubes the grid spawns; `None` where the count is only known at launch.
18    pub cubes: Option<u64>,
19    /// What one cube holds of its worker.
20    pub cube: CubeFootprint,
21    /// What the problem asks for, whichever routine runs it: its arithmetic, and the bytes its
22    /// operands hold, what a kernel reading each byte once would move. The same [`Work`] an
23    /// autotune table's roofline is drawn from.
24    pub demand: Option<Work>,
25    pub staging: Option<CubeStaging>,
26    pub work: Option<UnitWork>,
27}
28
29/// What one cube holds of its worker, from the grid.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct CubeFootprint {
32    pub units: u32,
33    /// Bytes of shared memory.
34    pub shared_memory: usize,
35}
36
37/// How one cube walks its work through global memory: in stages, each loaded while the stages
38/// before it compute, then drained.
39#[derive(Debug, Clone, PartialEq)]
40pub struct CubeStaging {
41    /// Arithmetic operations one cube performs, the cells it covers past the problem's edge
42    /// included.
43    pub operations: f64,
44    /// What one cube reads over its walk.
45    pub reads: Vec<GlobalStream>,
46    /// What one cube writes once its walk ends.
47    pub writes: Vec<GlobalStream>,
48    /// Stages one cube walks.
49    pub stages: u64,
50    /// Stages one cube holds at once: one where it loads a stage only once the last is computed,
51    /// more where it loads ahead.
52    pub stages_in_flight: u32,
53    /// Atomic adds into shared memory one cube issues as it drains.
54    pub drain_atomics: u64,
55}
56
57/// Bytes one cube moves through one operand, and the stretch of them a plane touches contiguously.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub struct GlobalStream {
60    pub bytes: u64,
61    /// Consecutive bytes a plane touches over the cube's walk: what a memory transaction is filled
62    /// from, a line a later stage finishes reading counted as filled.
63    pub run_bytes: usize,
64}
65
66/// What one unit holds of the work and how it computes it.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub struct UnitWork {
69    /// The instructions it runs on, which decide the rate.
70    pub instruction: ArithmeticInstruction,
71    /// 32-bit registers it keeps its work in: a lower bound, counting what the microkernel keeps
72    /// live and not what the compiler adds around it.
73    pub registers: u32,
74}
75
76impl UnitWork {
77    /// This work and `other` held by one unit at once, as a microkernel built from two runs them
78    /// one after the other within each step: their registers added, on the instruction both run.
79    pub fn beside(self, other: UnitWork) -> UnitWork {
80        debug_assert_eq!(
81            self.instruction, other.instruction,
82            "work held beside other work runs on the same instruction"
83        );
84        UnitWork {
85            instruction: self.instruction,
86            registers: self.registers + other.registers,
87        }
88    }
89}
90
91/// Which of the device's arithmetic rates a kernel runs at.
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
93pub enum ArithmeticInstruction {
94    /// Vector fused multiply-adds, one unit at a time.
95    Vector,
96    /// A matrix instruction a plane issues together.
97    Matrix,
98}