use std::fmt::Display;
use crate::routines::unit::UnitMatmul;
use cubecl::client::Client;
use cubek_matmul::{
definition::{MatmulElems, MatmulProblem},
multi_level::{
components::{stage::PartitionBuffering, tile::TileMatmulKind},
definition::BatchMatmulBlueprint,
routines::{
TileSizeSelection, UnitSmemBudget, batch::simple_unit::SimpleUnitSelectionArgs,
closest_factor_pair,
},
stage::{SwizzleMode, SwizzleModes},
},
routine::BlueprintStrategy,
};
#[derive(Clone, Copy, Debug)]
pub enum UnitStrategy {
Inferred(TileSizeSelection),
Fixed(UnitTiling),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct UnitTiling {
partition: (u32, u32, u32),
}
impl UnitTiling {
pub const NARROW: Self = Self::new(2, 1, 8);
pub const BALANCED: Self = Self::new(2, 2, 8);
pub const WIDE: Self = Self::new(2, 4, 8);
pub const DEEP: Self = Self::new(2, 2, 16);
pub const TALL: Self = Self::new(4, 2, 8);
const fn new(m: u32, n: u32, k: u32) -> Self {
Self {
partition: (m, n, k),
}
}
}
impl Display for UnitStrategy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Inferred(tile_size) => write!(f, "unit_{tile_size}"),
Self::Fixed(UnitTiling {
partition: (m, n, k),
}) => write!(f, "unit_{m}x{n}x{k}"),
}
}
}
impl UnitStrategy {
pub(crate) fn blueprint(
self,
client: &Client,
problem: &MatmulProblem,
dtypes: &MatmulElems,
) -> BlueprintStrategy<UnitMatmul> {
let partition = match self {
Self::Inferred(tile_size) => {
return BlueprintStrategy::Inferred(SimpleUnitSelectionArgs { tile_size });
}
Self::Fixed(tiling) => tiling.partition,
};
let hardware = &client.properties().hardware;
let plane_dim = match hardware.plane_size_min {
0 => 32,
plane_dim => plane_dim,
};
let stage = closest_factor_pair(1 << hardware.max_units_per_cube.min(128).ilog2());
let tiling = UnitSmemBudget {
dtypes,
stage_buffering: 1,
accumulator: problem.accumulator,
max_smem: hardware.max_shared_memory_size,
plane_dim,
}
.fit((4, 4, 4), partition, stage);
let mut builder =
BatchMatmulBlueprint::builder(TileMatmulKind::Register, tiling, plane_dim, problem)
.partition_buffering(PartitionBuffering::Single);
if client.properties().features.alignment && tiling.elements_per_stage_along_k() >= 32 {
builder = builder.shared_swizzle(SwizzleModes {
lhs: SwizzleMode::B128,
rhs: SwizzleMode::B128,
..Default::default()
});
}
BlueprintStrategy::Forced(builder.build())
}
}