use cubecl_core::ir::{ElemType, FloatKind};
use cubecl_runtime::{client::Client, throughput::ComputeCmmaConfig};
pub(super) struct Arithmetic;
impl Arithmetic {
pub(super) fn dtypes(client: &Client, dtype: ElemType) -> alloc::vec::Vec<ElemType> {
let mut dtypes = alloc::vec![dtype];
if let Some(accumulator) = Self::promoted(dtype)
&& client.properties().features.supports_type(accumulator)
{
dtypes.push(accumulator);
}
dtypes
}
pub(super) fn widths(client: &Client, dtype: ElemType) -> alloc::vec::Vec<usize> {
let widths: alloc::vec::Vec<usize> =
client.io_optimized_vector_sizes(dtype.size()).collect();
if widths.is_empty() {
alloc::vec![1]
} else {
widths
}
}
fn promoted(dtype: ElemType) -> Option<ElemType> {
let accumulator = ElemType::Float(FloatKind::F32);
let narrower_float =
matches!(dtype, ElemType::Float(_)) && dtype.size() < accumulator.size();
narrower_float.then_some(accumulator)
}
}
pub(super) struct CooperativeMatrix;
impl CooperativeMatrix {
pub(super) fn implemented(client: &Client, dtype: ElemType, config: ComputeCmmaConfig) -> bool {
client.properties().features.matmul.cmma.iter().any(|it| {
it.a_type == dtype
&& it.b_type == dtype
&& it.cd_type == config.accumulator_type
&& it.m as usize == config.cmma_dims.m
&& it.n as usize == config.cmma_dims.n
&& it.k as usize == config.cmma_dims.k
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use cubecl_core::ir::{IntKind, UIntKind};
const F32: ElemType = ElemType::Float(FloatKind::F32);
#[test]
fn nothing_as_wide_as_the_accumulator_is_promoted() {
assert_eq!(Arithmetic::promoted(F32), None);
assert_eq!(Arithmetic::promoted(ElemType::Float(FloatKind::F64)), None);
}
#[test]
fn an_integer_is_not_promoted() {
assert_eq!(Arithmetic::promoted(ElemType::Int(IntKind::I8)), None);
assert_eq!(Arithmetic::promoted(ElemType::UInt(UIntKind::U16)), None);
}
#[test]
fn every_float_narrower_than_the_accumulator_is_promoted() {
for dtype in [FloatKind::F16, FloatKind::BF16, FloatKind::E4M3] {
assert_eq!(Arithmetic::promoted(ElemType::Float(dtype)), Some(F32));
}
}
}