Skip to main content

cubek_std/microkernel/
base.rs

1use core::fmt::{Debug, Display};
2use cubecl::tile::launch::{Refusal, Vectorization};
3
4use crate::Hardware;
5use crate::microkernel::{CubePlanes, KernelEstimate};
6
7/// What one owner of a work item runs.
8///
9/// A value: the choice the hardware settled, sized by its settings, holding the microkernel it is
10/// built from where it is built from one. Its scope is in its name.
11pub trait Microkernel: Debug + Clone + PartialEq + Sized {
12    /// What one owner is handed, as far as the choice of microkernel depends on it.
13    type WorkItem: Debug + Clone;
14    /// The knobs a measurement settles.
15    type Settings: Debug + Clone + Display;
16    /// How the family names its operands, for [`Vectorization`].
17    type Operand: Debug + Copy + Eq;
18    /// The part of the problem one cube covers, as much of it as this microkernel reads: `()` for
19    /// one that reads only its own tiling. Where the cubes lie is its routine's placement.
20    type CubeSpace: Debug + Clone;
21
22    /// Why [`candidates`](Self::candidates) comes back empty on a device, when it does.
23    const DECLINE: &'static str;
24
25    /// The settings worth trying on this device, its default first: its own knobs, each setting
26    /// holding the one option it picked of the microkernel it is built from. A routine built on it
27    /// lists these, each at its own default, before it varies its own knobs; a microkernel built on
28    /// it picks from them by name.
29    fn settings(hw: &Hardware) -> Vec<Self::Settings>;
30
31    /// Every microkernel this device can run `item` as, best first; empty where it can run none.
32    ///
33    /// An iterator, and one that allocates nothing: [`best`](Self::best) takes its first item on
34    /// every `prepare`, so a list built to be read once would be built on every launch.
35    fn candidates(
36        hw: &Hardware,
37        item: &Self::WorkItem,
38        settings: &Self::Settings,
39    ) -> impl Iterator<Item = Self>;
40
41    /// Whether this microkernel serves `item` on any device, and why not where it does not: what
42    /// [`best`](Self::best) reports before [`DECLINE`](Self::DECLINE), which then names what a
43    /// device lacks. Every item, where it can say nothing finer.
44    ///
45    /// # Errors
46    ///
47    /// The reason this microkernel serves no such item.
48    fn admits(_item: &Self::WorkItem) -> Result<(), Refusal> {
49        Ok(())
50    }
51
52    /// Why [`candidates`](Self::candidates) comes back empty at `settings`: [`DECLINE`](Self::DECLINE),
53    /// where no setting asks the device for something finer.
54    fn decline(_settings: &Self::Settings) -> &'static str {
55        Self::DECLINE
56    }
57
58    /// The best candidate.
59    ///
60    /// # Errors
61    ///
62    /// [`admits`](Self::admits)'s reason, then [`decline`](Self::decline)'s where this device runs
63    /// none.
64    fn best(
65        hw: &Hardware,
66        item: &Self::WorkItem,
67        settings: &Self::Settings,
68    ) -> Result<Self, Refusal> {
69        Self::admits(item)?;
70        Self::candidates(hw, item, settings)
71            .next()
72            .ok_or(Refusal::Declined {
73                why: Self::decline(settings),
74            })
75    }
76
77    /// Enqueue what the accesses this microkernel's own code makes to the tiles it is handed
78    /// require of their widths, its cube covering `cube_space`, then hand
79    /// `vectorization` to the microkernels it is built from. Where those tiles live is its
80    /// walker's to know, not its own.
81    fn vectorize(
82        &self,
83        cube_space: &Self::CubeSpace,
84        vectorization: &mut Vectorization<Self::Operand>,
85    );
86
87    /// Set in `estimate` the parts this microkernel owns of a kernel running `item`, each of its
88    /// cubes of `planes` covering `cube_space`, then hand `estimate` to the microkernel it is built from:
89    /// the staging where it places the stage's reads, the work where its units hold it.
90    fn estimate(
91        &self,
92        item: &Self::WorkItem,
93        cube_space: &Self::CubeSpace,
94        planes: CubePlanes,
95        estimate: &mut KernelEstimate,
96    );
97}