use cubecl::prelude::*;
use super::leaf as reduce;
use crate::*;
#[cube]
impl<Acc: Numeric> Tile<Acc> {
pub fn reduce_axis<In: Numeric>(&mut self, input: &Tile<In>, #[comptime] monoid: Monoid) {
self.init_identity(monoid);
self.reduce_axis_accumulate(input, monoid);
}
pub fn reduce_axis_accumulate<In: Numeric>(
&mut self,
input: &Tile<In>,
#[comptime] monoid: Monoid,
) {
reduce_leaf(self, input, monoid)
}
}
#[cube]
pub(crate) fn reduce_leaf<Acc: Numeric, In: Numeric>(
acc: &mut Tile<Acc>,
input: &Tile<In>,
#[comptime] monoid: Monoid,
) {
let input_space = comptime!(input.place.space.clone());
let vector_size = input.vector_size();
comptime!(assert!(
input_space
.extent_at(input_space.rank() - 1)
.is_multiple_of(vector_size),
"reduce: the input's innermost extent must be divisible by its vector size"
));
let space = comptime!(acc.place.space.clone());
match &mut acc.kind {
TileKind::Memory(g) => {
reduce::memory(g, input, space, monoid);
}
TileKind::PlaneTile(t) => {
reduce_plane_tile(t, input, space, monoid);
}
TileKind::PlanePartition(p) => {
comptime!(assert!(
p.m_tiles == 1 && p.n_tiles == 1,
"reduce_leaf: a multi-tile partition must be contracted at its partition level"
));
let mut t = p.at(0usize, 0usize);
reduce_plane_tile(&mut t, input, space, monoid);
}
TileKind::TmaGmem(_) => panic!("reduce: a tma source is not an accumulator sink"),
TileKind::Procedural(_) | TileKind::Lines(_) => {
panic!("reduce: a procedural tile and the plane's units are not an accumulator sink")
}
}
}
#[cube]
fn reduce_plane_tile<Acc: Numeric, In: Numeric>(
tile: &mut PlaneTile<Acc>,
input: &Tile<In>,
#[comptime] acc_space: Space,
#[comptime] monoid: Monoid,
) {
match tile {
PlaneTile::Registers(d) => {
reduce::register_data(d, input, acc_space, monoid);
}
PlaneTile::Cmma(_) | PlaneTile::Mma(_) => {
panic!(
"reduce: a hardware mma fragment scatters its rows across units in a \
layout the elementwise walk cannot address; reduce into a register, \
Gmem or Smem accumulator instead"
);
}
}
}