Skip to main content

cubecl_ir/
features.rs

1use crate::{AddressType, ElemType, OpaqueType, SemanticType, Type};
2use alloc::collections::{BTreeMap, BTreeSet};
3
4use enumset::EnumSetType;
5
6pub use enumset::EnumSet;
7
8/// Features supported by a runtime
9#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
10pub struct Features {
11    /// Plane features supported by this runtime.
12    pub plane: EnumSet<Plane>,
13    /// Clustered launches and intra-cluster operations like cluster shared memory
14    pub cube_cluster: bool,
15    /// Enables changing the type of containers during kernel execution.
16    pub memory_reinterpret: bool,
17    /// Enables explicit alignment. If false, alignment still compiles, but isn't actually applied.
18    pub alignment: bool,
19
20    /// Type support
21    pub types: Types,
22    /// Matrix multiplication features
23    pub matmul: MatmulFeatures,
24
25    /// Whether `copy_async` is supported
26    pub copy_async: bool,
27    /// Tensor Memory Accelerator supported features
28    pub tma: EnumSet<Tma>,
29    /// Whether vectors can be read from / stored to addresses not aligned
30    /// with the `vector_size`
31    pub unaligned_io: bool,
32}
33
34/// Type support for a device
35#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
36pub struct Types {
37    /// Valid address types
38    pub address: BTreeSet<AddressType>,
39    /// Types supported by this runtime, and which usages they support.
40    pub elem: BTreeMap<ElemType, EnumSet<TypeUsage>>,
41    /// Semantic constructs supported by this runtime.
42    pub semantic: BTreeSet<SemanticType>,
43    /// Opaque types supported by this runtime.
44    pub opaque: BTreeSet<OpaqueType>,
45    /// Supported vector types for atomic ops, only specific vectorizations for specific types are
46    /// supported here. Not all vector types are supported as scalars, i.e. Vulkan on Nvidia only
47    /// supports vectorized `f16`, not scalar. Only use the exact vectorizations registered here.
48    /// These may not be supported everywhere - in practice, f32 vectors are only supported in global
49    /// memory.
50    pub atomic: BTreeMap<Type, EnumSet<AtomicUsage>>,
51}
52
53/// Matrix multiplication-related features
54#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
55pub struct MatmulFeatures {
56    /// The cmma feature enables cooperative matrix-multiply and accumulate operations.
57    pub cmma: BTreeSet<MmaConfig>,
58    /// Cube MMA is like cmma but at the cube level, rather than the plane level.
59    /// Loading may be staged in shared memory by the driver on Vulkan - check
60    /// [`cube_mma_reserved_shared_memory`](crate::HardwareProperties::cube_mma_reserved_shared_memory)
61    /// to take this into account when generating a matmul config.
62    pub cube_mma: BTreeSet<CubeMmaConfig>,
63    /// The manual MMA feature enables cooperative matrix-multiply with manually managed data
64    /// movement
65    pub mma: BTreeSet<MmaConfig>,
66    /// Scaled MMA allows combining matrix multiplication with unscaling quantized values into a single
67    /// instruction. Scales must fit a specific layout and block size.
68    pub scaled_mma: BTreeSet<ScaledMmaConfig>,
69    /// Types supported for ldmatrix, if any
70    pub ldmatrix: BTreeSet<ElemType>,
71    /// Types supported by stmatrix, if any
72    pub stmatrix: BTreeSet<ElemType>,
73    /// Whether tensor addressing is supported for CMMA load/store
74    pub cmma_tensor_addressing: bool,
75}
76
77/// Operations allowed for this type. CMMA is defined separately.
78#[derive(Debug, Hash, PartialOrd, Ord, EnumSetType)]
79pub enum TypeUsage {
80    /// Conversion to/from the type. All types should support this.
81    Conversion,
82    /// All math/logic instructions except dot product
83    Arithmetic,
84    /// Dot product, mainly for BF16 on Intel
85    DotProduct,
86    /// Whether this type can be stored in a buffer
87    Buffer,
88}
89
90impl TypeUsage {
91    pub fn all() -> EnumSet<Self> {
92        EnumSet::all()
93    }
94
95    pub fn no_store() -> EnumSet<Self> {
96        TypeUsage::Conversion | TypeUsage::Arithmetic
97    }
98
99    pub fn maybe_store(storable: bool) -> EnumSet<Self> {
100        if storable {
101            EnumSet::all()
102        } else {
103            Self::no_store()
104        }
105    }
106}
107
108/// Atomic operations allowed for this type.
109#[derive(Debug, Hash, PartialOrd, Ord, EnumSetType)]
110pub enum AtomicUsage {
111    /// Atomic loads and stores
112    LoadStore,
113    /// Atomic exchange
114    Exchange,
115    /// Atomic add/sub
116    Add,
117    /// Atomic min/max
118    MinMax,
119    /// Atomic bitwise and/or/xor
120    Bitwise,
121    /// Atomic compare-and-exchange
122    CompareExchange,
123}
124
125impl AtomicUsage {
126    pub fn all() -> EnumSet<Self> {
127        EnumSet::all()
128    }
129}
130
131/// Supported plane features
132#[derive(Debug, Hash, PartialOrd, Ord, EnumSetType)]
133pub enum Plane {
134    /// Basic plane-wide operations
135    Ops,
136    /// Plane-wide sync
137    Sync,
138    /// Allows using plane operations with divergent control flow.
139    NonUniformControlFlow,
140}
141
142/// Shape and element types of a valid MMA configuration
143#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
144#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
145pub struct MmaConfig {
146    /// Element of the A matrix
147    pub a_type: ElemType,
148    /// Element of the B matrix
149    pub b_type: ElemType,
150    /// Element of the C/D matrices
151    pub cd_type: ElemType,
152    /// The size of the matrix on the `m` dimension
153    pub m: u32,
154    /// The size of the matrix on the `n` dimension
155    pub n: u32,
156    /// The size of the matrix on the `k` dimension
157    pub k: u32,
158}
159
160/// Shape and element types of a valid flexible MMA configuration
161/// Only Vulkan for now, but this should also be usable for wgmma/xmma on datacenter CUDA.
162/// Actual matrix size must be multiple of `granularity` and `<= max`.
163#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
164#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
165pub struct CubeMmaConfig {
166    /// Element of the A matrix
167    pub a_type: ElemType,
168    /// Element of the B matrix
169    pub b_type: ElemType,
170    /// Element of the C/D matrices
171    pub cd_type: ElemType,
172    /// The granularity of the matrix on the `m` dimension
173    pub m_granularity: u32,
174    /// The maximum value for `m`
175    pub m_max: u32,
176    /// The size of the matrix on the `n` dimension
177    pub n_granularity: u32,
178    /// The maximum value for `n`
179    pub n_max: u32,
180    /// The size of the matrix on the `k` dimension
181    pub k_granularity: u32,
182    /// The maximum value for `k`
183    pub k_max: u32,
184    /// The number of units that must be in the cube for this configuration to be valid.
185    /// `None` means it's always valid (but might still have an optimal value).
186    pub units_per_block: Option<u32>,
187}
188
189/// Shape and element types of a valid block-scaled MMA configuration
190#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
191#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
192pub struct ScaledMmaConfig {
193    /// Element of the A matrix
194    pub a_type: ElemType,
195    /// Element of the B matrix
196    pub b_type: ElemType,
197    /// Element of the C/D matrices
198    pub cd_type: ElemType,
199    /// Element of the blocks scales
200    pub scales_type: ElemType,
201    /// The size of the matrix on the `m` dimension
202    pub m: u32,
203    /// The size of the matrix on the `n` dimension
204    pub n: u32,
205    /// The size of the matrix on the `k` dimension
206    pub k: u32,
207    /// Number of scales per tile row/col.
208    /// A scale factor of 2 means `m x 2` scales for A and `2 x n` for B (in CUDA)
209    /// Scales blocks must be organized along the natural `vector_layout` of the operation
210    pub scales_factor: u32,
211}
212
213/// Atomic features that may be supported by a ``Runtime``.
214#[derive(Debug, PartialOrd, Ord, EnumSetType)]
215pub enum Tma {
216    /// Base feature set for tensor memory accelerator features. Includes tiling and im2col
217    Base,
218    /// im2colWide encoding for tensor map.
219    Im2colWide,
220    /// Different atomicities for 128-byte swizzle, i.e. 128-byte with 32-byte atomicity.
221    SwizzleAtomicity,
222}
223
224impl Features {
225    /// Get the usages for a type
226    pub fn type_usage(&self, ty: ElemType) -> EnumSet<TypeUsage> {
227        self.types
228            .elem
229            .get(&ty)
230            .cloned()
231            .unwrap_or_else(EnumSet::empty)
232    }
233
234    /// Get the usages for an atomic type
235    pub fn atomic_type_usage(&self, ty: Type) -> EnumSet<AtomicUsage> {
236        self.types
237            .atomic
238            .get(&ty)
239            .cloned()
240            .unwrap_or_else(EnumSet::empty)
241    }
242
243    /// Whether the type is supported in any way
244    pub fn supports_type(&self, ty: impl Into<Type>) -> bool {
245        match ty.into() {
246            Type::Semantic(semantic_type) => self.types.semantic.contains(&semantic_type),
247            Type::Opaque(opaque_type) => self.types.opaque.contains(&opaque_type),
248            ty => self.types.elem.contains_key(&ty.elem_type()),
249        }
250    }
251
252    /// Whether the address type is supported in any way
253    pub fn supports_address(&self, ty: impl Into<AddressType>) -> bool {
254        self.types.address.contains(&ty.into())
255    }
256}