1#![allow(non_snake_case)]
18
19use teeny_core::dtype::Num;
20use teeny_macros::kernel;
21use teeny_triton::triton::{
22 types::{AddOffsets, Comparison, Tensor},
23 *,
24};
25
26#[kernel]
35pub fn avgpool1d_forward<T: Triton, D: Num, const KL: i32, const STRIDE: i32, const BLOCK_OL: i32>(
36 input_ptr: T::Pointer<D>,
37 output_ptr: T::Pointer<D>,
38 _B: i32,
39 C: i32,
40 L: i32,
41 OL: i32,
42) where
43 T::I32Tensor: Tensor<i32, 1>,
44 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
45 T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
46{
47 let pid = T::program_id(Axis::X);
48 let num_ol_tiles = T::cdiv(OL, BLOCK_OL);
49
50 let ol_tile = pid % num_ol_tiles;
51 let bc = pid / num_ol_tiles;
52 let c = bc % C;
53 let b = bc / C;
54
55 let ol_start = ol_tile * BLOCK_OL;
56 let ol_range = T::arange(0, BLOCK_OL) + ol_start;
57 let ol_mask = ol_range.lt(OL);
58
59 let in_bc_base = (b * C + c) * L;
60 let out_bc_base = (b * C + c) * OL;
61
62 let mut acc = T::zeros::<D>(&[BLOCK_OL]);
63
64 let loop_bound = KL;
65 for kl in 0..loop_bound {
66 let il_range = ol_range * STRIDE + kl;
67 let in_offsets = il_range + in_bc_base;
68 let tile = T::load(
69 input_ptr.add_offsets(in_offsets),
70 Some(ol_mask),
71 Some(T::zeros::<D>(&[BLOCK_OL])),
72 &[],
73 None,
74 None,
75 None,
76 false,
77 );
78 acc = acc + tile;
79 }
80
81 let ksize_1 = T::full::<i32>(&[1], KL);
82 let ksize_f_1 = T::cast::<i32, D>(ksize_1, None, false);
83 let ksize = T::broadcast_to(ksize_f_1, &[BLOCK_OL]);
84 let result = acc / ksize;
85
86 let out_offsets = ol_range + out_bc_base;
87 T::store(
88 output_ptr.add_offsets(out_offsets),
89 result,
90 Some(ol_mask),
91 &[],
92 None,
93 None,
94 );
95}
96
97#[kernel]
104pub fn avgpool1d_backward<
105 T: Triton,
106 D: Num,
107 const KL: i32,
108 const STRIDE: i32,
109 const BLOCK_OL: i32,
110>(
111 dy_ptr: T::Pointer<D>,
112 dx_ptr: T::Pointer<D>,
113 _B: i32,
114 C: i32,
115 L: i32,
116 OL: i32,
117) where
118 T::I32Tensor: Tensor<i32, 1>,
119 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
120 T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
121{
122 let pid = T::program_id(Axis::X);
123 let num_ol_tiles = T::cdiv(OL, BLOCK_OL);
124
125 let ol_tile = pid % num_ol_tiles;
126 let bc = pid / num_ol_tiles;
127 let c = bc % C;
128 let b = bc / C;
129
130 let ol_start = ol_tile * BLOCK_OL;
131 let ol_range = T::arange(0, BLOCK_OL) + ol_start;
132 let ol_mask = ol_range.lt(OL);
133
134 let dy_bc_base = (b * C + c) * OL;
135 let dx_bc_base = (b * C + c) * L;
136
137 let dy_offsets = ol_range + dy_bc_base;
138 let dy_tile = T::load(
139 dy_ptr.add_offsets(dy_offsets),
140 Some(ol_mask),
141 Some(T::zeros::<D>(&[BLOCK_OL])),
142 &[],
143 None,
144 None,
145 None,
146 false,
147 );
148 let ksize_1 = T::full::<i32>(&[1], KL);
149 let ksize_f_1 = T::cast::<i32, D>(ksize_1, None, false);
150 let ksize = T::broadcast_to(ksize_f_1, &[BLOCK_OL]);
151 let grad = dy_tile / ksize;
152
153 let loop_bound = KL;
154 for kl in 0..loop_bound {
155 let il_range = ol_range * STRIDE + kl;
156 let dx_offsets = il_range + dx_bc_base;
157 T::atomic_add(
158 dx_ptr.add_offsets(dx_offsets),
159 grad,
160 Some(ol_mask),
161 None,
162 None,
163 );
164 }
165}
166
167pub struct Avgpool1dOp<'a, T: Num> {
168 pub forward: Avgpool1dForward<T>,
169 pub backward: Avgpool1dBackward<T>,
170 _marker: core::marker::PhantomData<&'a ()>,
171}