use cubecl::{prelude::*, std::tensor::layout::Coords2d};
use crate::tile::Partitioner;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct PlaneFlowCounts {
pub main_flow: u32,
pub load_only: u32,
}
impl PlaneFlowCounts {
pub fn total_count(&self) -> u32 {
self.main_flow + self.load_only
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum PlaneFlowPartitionRule {
MainFlowOnly,
LoadOnlyFirst { load_only: u32 },
LoadOnlyLast { main_flow: u32 },
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct PlaneFlowConfig {
pub counts: PlaneFlowCounts,
pub partition_rule: PlaneFlowPartitionRule,
}
impl PlaneFlowConfig {
pub fn new_unspecialized(num_planes: u32) -> Self {
Self {
counts: PlaneFlowCounts {
main_flow: num_planes,
load_only: 0,
},
partition_rule: PlaneFlowPartitionRule::MainFlowOnly,
}
}
pub fn main_flow_count(&self) -> u32 {
self.counts.main_flow
}
pub fn has_specialization(&self) -> bool {
self.counts.load_only > 0
}
}
#[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum InputLoadFlow {
#[default]
MainOnly,
LoadOnly,
}
impl InputLoadFlow {
pub fn has_specialization(&self) -> bool {
matches!(self, InputLoadFlow::LoadOnly)
}
}
#[derive(CubeType, Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct PartitionThreshold {
#[cube(comptime)]
threshold: u32,
}
#[derive(CubeType, Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum PlaneFlowPartition {
MainFlowOnly,
LoadOnlyFirst(PartitionThreshold),
LoadOnlyLast(PartitionThreshold),
}
#[cube]
impl PlaneFlowPartition {
pub fn new(#[comptime] comptime_rule: PlaneFlowPartitionRule) -> PlaneFlowPartition {
match comptime_rule {
PlaneFlowPartitionRule::MainFlowOnly => PlaneFlowPartition::new_MainFlowOnly(),
PlaneFlowPartitionRule::LoadOnlyFirst { load_only } => {
PlaneFlowPartition::new_LoadOnlyFirst(PartitionThreshold {
threshold: load_only,
})
}
PlaneFlowPartitionRule::LoadOnlyLast { main_flow } => {
PlaneFlowPartition::new_LoadOnlyLast(PartitionThreshold {
threshold: main_flow,
})
}
}
}
pub fn compute_index(self) -> u32 {
match self {
PlaneFlowPartition::MainFlowOnly => UNIT_POS_Y,
PlaneFlowPartition::LoadOnlyFirst(load_only) => UNIT_POS_Y - load_only.threshold,
PlaneFlowPartition::LoadOnlyLast(_) => UNIT_POS_Y,
}
}
pub fn load_index(self, #[comptime] specialization_tensor_config: InputLoadFlow) -> u32 {
match self {
PlaneFlowPartition::MainFlowOnly => UNIT_POS_Y,
PlaneFlowPartition::LoadOnlyFirst(load_only) => match specialization_tensor_config {
InputLoadFlow::MainOnly => UNIT_POS_Y - load_only.threshold,
InputLoadFlow::LoadOnly => UNIT_POS_Y,
},
PlaneFlowPartition::LoadOnlyLast(main_flow) => match specialization_tensor_config {
InputLoadFlow::LoadOnly => UNIT_POS_Y - main_flow.threshold,
InputLoadFlow::MainOnly => UNIT_POS_Y,
},
}
}
pub fn elect_load_leader(&self) -> bool {
let plane_id = plane_broadcast(UNIT_POS_Y, 0u32);
let is_elected_plane = match self {
PlaneFlowPartition::MainFlowOnly | PlaneFlowPartition::LoadOnlyFirst(_) => {
plane_id == 0
}
PlaneFlowPartition::LoadOnlyLast(main_flow) => plane_id == main_flow.threshold,
};
is_elected_plane && plane_elect()
}
pub fn is_load_plane(self) -> bool {
match self {
PlaneFlowPartition::MainFlowOnly => false,
PlaneFlowPartition::LoadOnlyFirst(load_only) => UNIT_POS_Y < load_only.threshold,
PlaneFlowPartition::LoadOnlyLast(main_flow) => UNIT_POS_Y >= main_flow.threshold,
}
}
pub fn is_compute_plane(self) -> bool {
let plane_id = plane_broadcast(UNIT_POS_Y, 0u32);
match self {
PlaneFlowPartition::MainFlowOnly => true,
PlaneFlowPartition::LoadOnlyFirst(load_only) => plane_id >= load_only.threshold,
PlaneFlowPartition::LoadOnlyLast(main_flow) => plane_id < main_flow.threshold,
}
}
}
#[cube]
pub fn partition_coordinates<P: Partitioner>(
#[comptime] role_rule_config: PlaneFlowPartitionRule,
#[comptime] plane_dim: u32,
#[comptime] num_partitions_col: u32,
) -> Coords2d {
let compute_index = PlaneFlowPartition::new(role_rule_config).compute_index();
P::coordinates(compute_index, plane_dim, num_partitions_col)
}