cubecl_ir/features.rs
1use crate::{AddressType, OpaqueType, SemanticType, StorageType, 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 storage: BTreeMap<StorageType, 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<StorageType>,
71 /// Types supported by stmatrix, if any
72 pub stmatrix: BTreeSet<StorageType>,
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 add/sub
114 Add,
115 /// Atomic min/max
116 MinMax,
117 /// Atomic bitwise and/or/xor
118 Bitwise,
119 /// Atomic compare-and-exchange
120 CompareExchange,
121}
122
123impl AtomicUsage {
124 pub fn all() -> EnumSet<Self> {
125 EnumSet::all()
126 }
127}
128
129/// Supported plane features
130#[derive(Debug, Hash, PartialOrd, Ord, EnumSetType)]
131pub enum Plane {
132 /// Basic plane-wide operations
133 Ops,
134 /// Plane-wide sync
135 Sync,
136 /// Allows using plane operations with divergent control flow.
137 NonUniformControlFlow,
138}
139
140/// Shape and element types of a valid MMA configuration
141#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
142#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
143pub struct MmaConfig {
144 /// Element of the A matrix
145 pub a_type: StorageType,
146 /// Element of the B matrix
147 pub b_type: StorageType,
148 /// Element of the C/D matrices
149 pub cd_type: StorageType,
150 /// The size of the matrix on the `m` dimension
151 pub m: u32,
152 /// The size of the matrix on the `n` dimension
153 pub n: u32,
154 /// The size of the matrix on the `k` dimension
155 pub k: u32,
156}
157
158/// Shape and element types of a valid flexible MMA configuration
159/// Only Vulkan for now, but this should also be usable for wgmma/xmma on datacenter CUDA.
160/// Actual matrix size must be multiple of `granularity` and `<= max`.
161#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
162#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
163pub struct CubeMmaConfig {
164 /// Element of the A matrix
165 pub a_type: StorageType,
166 /// Element of the B matrix
167 pub b_type: StorageType,
168 /// Element of the C/D matrices
169 pub cd_type: StorageType,
170 /// The granularity of the matrix on the `m` dimension
171 pub m_granularity: u32,
172 /// The maximum value for `m`
173 pub m_max: u32,
174 /// The size of the matrix on the `n` dimension
175 pub n_granularity: u32,
176 /// The maximum value for `n`
177 pub n_max: u32,
178 /// The size of the matrix on the `k` dimension
179 pub k_granularity: u32,
180 /// The maximum value for `k`
181 pub k_max: u32,
182 /// The number of units that must be in the cube for this configuration to be valid.
183 /// `None` means it's always valid (but might still have an optimal value).
184 pub units_per_block: Option<u32>,
185}
186
187/// Shape and element types of a valid block-scaled MMA configuration
188#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
189#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
190pub struct ScaledMmaConfig {
191 /// Element of the A matrix
192 pub a_type: StorageType,
193 /// Element of the B matrix
194 pub b_type: StorageType,
195 /// Element of the C/D matrices
196 pub cd_type: StorageType,
197 /// Element of the blocks scales
198 pub scales_type: StorageType,
199 /// The size of the matrix on the `m` dimension
200 pub m: u32,
201 /// The size of the matrix on the `n` dimension
202 pub n: u32,
203 /// The size of the matrix on the `k` dimension
204 pub k: u32,
205 /// Number of scales per tile row/col.
206 /// A scale factor of 2 means `m x 2` scales for A and `2 x n` for B (in CUDA)
207 /// Scales blocks must be organized along the natural `vector_layout` of the operation
208 pub scales_factor: u32,
209}
210
211/// Atomic features that may be supported by a ``Runtime``.
212#[derive(Debug, PartialOrd, Ord, EnumSetType)]
213pub enum Tma {
214 /// Base feature set for tensor memory accelerator features. Includes tiling and im2col
215 Base,
216 /// im2colWide encoding for tensor map.
217 Im2colWide,
218 /// Different atomicities for 128-byte swizzle, i.e. 128-byte with 32-byte atomicity.
219 SwizzleAtomicity,
220}
221
222impl Features {
223 /// Get the usages for a type
224 pub fn type_usage(&self, ty: StorageType) -> EnumSet<TypeUsage> {
225 self.types
226 .storage
227 .get(&ty)
228 .cloned()
229 .unwrap_or_else(EnumSet::empty)
230 }
231
232 /// Get the usages for an atomic type
233 pub fn atomic_type_usage(&self, ty: Type) -> EnumSet<AtomicUsage> {
234 self.types
235 .atomic
236 .get(&ty)
237 .cloned()
238 .unwrap_or_else(EnumSet::empty)
239 }
240
241 /// Whether the type is supported in any way
242 pub fn supports_type(&self, ty: impl Into<Type>) -> bool {
243 match ty.into() {
244 Type::Semantic(semantic_type) => self.types.semantic.contains(&semantic_type),
245 Type::Opaque(opaque_type) => self.types.opaque.contains(&opaque_type),
246 ty => self.types.storage.contains_key(&ty.storage_type()),
247 }
248 }
249
250 /// Whether the address type is supported in any way
251 pub fn supports_address(&self, ty: impl Into<AddressType>) -> bool {
252 self.types.address.contains(&ty.into())
253 }
254}