cubecl_ir/
properties.rs

1use crate::{
2    AddressType, SemanticType, StorageType, Type, TypeHash,
3    features::{Features, TypeUsage},
4};
5use cubecl_common::profile::TimingMethod;
6use enumset::EnumSet;
7
8/// Properties of the device related to the accelerator hardware.
9///
10/// # Plane size min/max
11///
12/// This is a range of possible values for the plane size.
13///
14/// For Nvidia GPUs and HIP, this is a single fixed value.
15///
16/// For wgpu with AMD GPUs this is a range of possible values, but the actual configured value
17/// is undefined and can only be queried at runtime. Should usually be 32, but not guaranteed.
18///
19/// For Intel GPUs, this is variable based on the number of registers used in the kernel. No way to
20/// query this at compile time is currently available. As a result, the minimum value should usually
21/// be assumed.
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct HardwareProperties {
24    /// The maximum size of a single load instruction, in bits. Used for optimized line sizes.
25    pub load_width: u32,
26    /// The minimum size of a plane on this device
27    pub plane_size_min: u32,
28    /// The maximum size of a plane on this device
29    pub plane_size_max: u32,
30    /// minimum number of bindings for a kernel that can be used at once.
31    pub max_bindings: u32,
32    /// Maximum amount of shared memory, in bytes
33    pub max_shared_memory_size: usize,
34    /// Maximum `CubeCount` in x, y and z dimensions
35    pub max_cube_count: (u32, u32, u32),
36    /// Maximum number of total units in a cube
37    pub max_units_per_cube: u32,
38    /// Maximum `CubeDim` in x, y, and z dimensions
39    pub max_cube_dim: (u32, u32, u32),
40    /// Number of streaming multiprocessors (SM), if available
41    pub num_streaming_multiprocessors: Option<u32>,
42    /// Number of available parallel cpu units, if the runtime is CPU.
43    pub num_cpu_cores: Option<u32>,
44    /// Number of tensor cores per SM, if any
45    pub num_tensor_cores: Option<u32>,
46    /// The minimum tiling dimension for a single axis in tensor cores.
47    ///
48    /// For a backend that only supports 16x16x16, the value would be 16.
49    /// For a backend that also supports 32x8x16, the value would be 8.
50    pub min_tensor_cores_dim: Option<u32>,
51}
52
53/// Properties of the device related to allocation.
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct MemoryDeviceProperties {
56    /// The maximum nr. of bytes that can be allocated in one go.
57    pub max_page_size: u64,
58    /// The required memory offset alignment in bytes.
59    pub alignment: u64,
60}
61
62/// Properties of what the device can do, like what `Feature` are
63/// supported by it and what its memory properties are.
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct DeviceProperties {
66    /// The features supported by the runtime.
67    pub features: Features,
68    /// The memory properties of this client.
69    pub memory: MemoryDeviceProperties,
70    /// The topology properties of this client.
71    pub hardware: HardwareProperties,
72    /// The method used for profiling on the device.
73    pub timing_method: TimingMethod,
74}
75
76impl TypeHash for DeviceProperties {
77    fn write_hash(_hasher: &mut impl core::hash::Hasher) {
78        // ignored.
79    }
80}
81
82impl DeviceProperties {
83    /// Create a new feature set with the given features and memory properties.
84    pub fn new(
85        features: Features,
86        memory_props: MemoryDeviceProperties,
87        hardware: HardwareProperties,
88        timing_method: TimingMethod,
89    ) -> Self {
90        DeviceProperties {
91            features,
92            memory: memory_props,
93            hardware,
94            timing_method,
95        }
96    }
97
98    /// Get the usages for a type
99    pub fn type_usage(&self, ty: StorageType) -> EnumSet<TypeUsage> {
100        self.features.type_usage(ty)
101    }
102
103    /// Whether the type is supported in any way
104    pub fn supports_type(&self, ty: impl Into<Type>) -> bool {
105        self.features.supports_type(ty)
106    }
107
108    /// Whether the address type is supported in any way
109    pub fn supports_address(&self, ty: impl Into<AddressType>) -> bool {
110        self.features.supports_address(ty)
111    }
112
113    /// Register an address type to the features
114    pub fn register_address_type(&mut self, ty: impl Into<AddressType>) {
115        self.features.address_types.insert(ty.into());
116    }
117
118    /// Register a storage type to the features
119    pub fn register_type_usage(
120        &mut self,
121        ty: impl Into<StorageType>,
122        uses: impl Into<EnumSet<TypeUsage>>,
123    ) {
124        *self.features.storage_types.entry(ty.into()).or_default() |= uses.into();
125    }
126
127    /// Register a semantic type to the features
128    pub fn register_semantic_type(&mut self, ty: SemanticType) {
129        self.features.semantic_types.insert(ty);
130    }
131}