use cubecl::{
prelude::barrier::Barrier,
prelude::*,
std::tensor::{ViewMut, layout::CoordsDyn},
};
use crate::*;
#[derive(CubeType, Clone)]
#[expand(derive(Clone))]
pub(crate) struct TmaData<T: Numeric> {
view: ViewMut<'static, T, CoordsDyn>,
pos: CoordsDyn,
pub(crate) bound: CoordsDyn,
#[cube(comptime)]
pub(crate) units: usize,
}
#[cube]
impl<T: Numeric> TmaData<T> {
pub(crate) fn from_tensor_map(
view: ViewMut<'static, T, CoordsDyn>,
#[comptime] rank: usize,
#[comptime] units: usize,
) -> TmaData<T> {
let bound = view.shape();
let mut pos = CoordsDyn::new();
#[unroll]
for _ in 0..rank {
pos.push(0u32);
}
TmaData::<T> {
view,
pos,
bound,
units,
}
}
}
#[cube]
impl<T: Numeric> TmaData<T> {
pub(crate) fn stage_into(&self, dst: &mut Memory<T>, barrier: &Shared<Barrier>) {
comptime!(dst.layout.rows.assert_in_order(
"TmaData::stage_into",
"a TMA box lands its rows dense and in order"
));
self.view.tensor_map_load(
barrier,
dst.store.buffer_mut().downcast_mut(),
self.pos.clone(),
);
}
pub(crate) fn load_into(&self, dst: &mut Memory<T>) {
comptime!(assert!(
dst.address == AddressSpace::Shared,
"TmaData::load_into: a tensor map bulk-copies into shared memory only"
));
let barrier = Barrier::shared(CUBE_DIM, UNIT_POS == 0);
sync_async_proxy_shared();
let expected = select(UNIT_POS == 0, dst.size_bytes(), 0);
if UNIT_POS == 0 {
self.stage_into(dst, &barrier);
}
let token = barrier.arrive_and_expect_tx(1, expected);
barrier.wait(token);
}
pub(crate) fn at(&self, step: &Step, #[comptime] space: Space) -> TmaData<T> {
let mut pos = CoordsDyn::new();
#[unroll]
for p in 0..space.rank() {
let axis = space.axis_at(p);
match comptime!(step.level.tile(axis)) {
Some(tile) => {
let index = step.coord(axis);
pos.push(self.pos[p] + (index * tile) as u32);
}
None => pos.push(self.pos[p]),
}
}
TmaData::<T> {
view: self.view.clone(),
pos,
bound: self.bound.clone(),
units: self.units,
}
}
}