cubecl_tile/launch/arg/
accumulate.rs1use cubecl::define_size;
4use cubecl::ir::{ExpandValue, VectorSize};
5use cubecl::prelude::*;
6use cubecl::unexpanded;
7use cubecl_std::tensor::{
8 ErasedTensor, ErasedTensorExpand, ErasedTensorOperationsExpand, WriteOnly, WritesLines,
9};
10
11use crate::*;
12
13#[derive(CubeType, CubeLaunch)]
16pub struct AccumulateArg<'a, E: Numeric> {
17 pub tensor: &'a Tensor<Atomic<E>>,
18 #[cube(comptime)]
20 pub width: usize,
21 #[cube(comptime)]
22 pub spec: TileSpec,
23}
24
25#[cube]
26impl<'a, E: Numeric> AccumulateArg<'a, E> {
27 pub fn tile(&self, partitioning: &Partitioning) -> Tile {
29 let space = comptime!(partitioning.clone());
30 let geometry = RuntimeGeometry::of_tensor::<Atomic<E>>(
32 self.tensor,
33 comptime!(self.spec.projection.physical_rank()),
34 );
35 let sink = atomic_sink::<E>(self.tensor, comptime!(self.width));
36 GlobalOperand::sink(
37 sink,
38 geometry,
39 comptime!(self.width),
40 comptime!(space.space().clone()),
41 comptime!(self.spec.clone()),
42 Write::Accumulate,
43 )
44 .tile::<E>(comptime!(space.levels().to_vec()))
45 }
46}
47
48fn atomic_sink<E: Numeric>(
50 _values: &Tensor<Atomic<E>>,
51 _width: usize,
52) -> ErasedTensor<E, WriteOnly> {
53 unexpanded!()
54}
55
56mod atomic_sink {
57 use super::*;
58
59 pub(super) fn expand<E: Numeric>(
60 _scope: &Scope,
61 values: &<Tensor<Atomic<E>> as CubeType>::ExpandType,
62 width: usize,
63 ) -> ErasedTensorExpand<E, WriteOnly> {
64 ErasedTensorExpand::new(AtomicAccumulate::<E> {
65 values: ExpandTypeClone::clone_unchecked(values),
66 width,
67 })
68 }
69}
70
71struct AtomicAccumulate<E: Numeric> {
73 values: <Tensor<Atomic<E>> as CubeType>::ExpandType,
74 width: usize,
75}
76
77define_size!(Line);
80
81impl<E: Numeric> ErasedTensorOperationsExpand<E> for AtomicAccumulate<E> {
82 fn __expand_vector_size_method(&self, _scope: &Scope) -> VectorSize {
83 self.width
84 }
85
86 fn __expand_lines_method(&self, scope: &Scope) -> NativeExpand<usize> {
89 let scalars = self.values.__expand_buffer_len_method(scope);
90 let width = self.width.__expand_runtime_method(scope);
91 scalars.__expand_div_method(scope, width)
92 }
93
94 fn __expand_write_line_method(
95 &mut self,
96 scope: &Scope,
97 index: NativeExpand<usize>,
98 value: ExpandValue,
99 ) {
100 scope.register_size::<Line>(self.width);
101 accumulate_line::expand::<E, Line>(scope, &self.values, index, value.into());
102 }
103}
104
105impl<E: Numeric> WritesLines<E> for AtomicAccumulate<E> {}
106
107#[cube]
109fn accumulate_line<E: Numeric, N: Size>(
110 values: &Tensor<Atomic<E>>,
111 index: usize,
112 value: Vector<E, N>,
113) {
114 let base = index * N::value();
115 #[unroll]
116 for k in 0..N::value() {
117 values[base + k].fetch_add(value.extract(k));
118 }
119}