1use cubecl::client::Client;
8use cubek_matmul::{
9 definition::MatmulElems,
10 multi_level::{
11 components::tile::TileMatmulKind, definition::BatchMatmulBlueprint, routines::TilingArgs,
12 },
13 routine::BlueprintStrategy,
14};
15
16use crate::{components::ConvolutionOperation, definition::ConvBlueprint};
17
18fn blueprint_operation(blueprint: &ConvBlueprint) -> ConvolutionOperation {
19 match blueprint {
20 ConvBlueprint::Forward(_) => ConvolutionOperation::Forward,
21 ConvBlueprint::BackwardData(_) => ConvolutionOperation::BackwardData,
22 ConvBlueprint::BackwardWeight(_) => ConvolutionOperation::BackwardWeight,
23 }
24}
25
26use crate::{
27 components::ConvSetupError,
28 kernels::{backward_data, backward_weight, forward},
29 launch::{
30 ConvAlgorithm, ConvolutionArgs, ConvolutionInputs, Strategy, strategy::AcceleratedTileKind,
31 unit,
32 },
33 routines::{
34 Routine,
35 simple::{
36 SimpleAsyncCyclicConv, SimpleAsyncStridedConv, SimpleAsyncTmaConv,
37 SimpleSyncCyclicConv, SimpleSyncStridedConv, SimpleSyncTilewiseConv,
38 },
39 specialized::{
40 SpecializedAsyncCyclicConv, SpecializedAsyncStridedConv, SpecializedTmaConv,
41 },
42 },
43};
44
45pub(crate) fn tile_kind_to_dispatch(kind: AcceleratedTileKind) -> TileMatmulKind {
47 match kind {
48 AcceleratedTileKind::Cmma => TileMatmulKind::Cmma,
49 AcceleratedTileKind::Mma => TileMatmulKind::Mma,
50 }
51}
52
53#[allow(clippy::result_large_err)]
59pub fn launch_ref<const N_SPATIAL: usize>(
60 strategy: &Strategy,
61 client: &Client,
62 inputs: ConvolutionInputs,
63 args: ConvolutionArgs<N_SPATIAL>,
64 dtypes: MatmulElems,
65) -> Result<(), ConvSetupError> {
66 let (algorithm, tile_kind, forced_matmul) = match strategy {
67 Strategy::Inferred {
68 algorithm,
69 tile_kind,
70 } => (*algorithm, *tile_kind, None),
71 Strategy::Forced {
72 algorithm,
73 blueprint,
74 } => {
75 debug_assert_eq!(
76 inputs.operation(),
77 blueprint_operation(blueprint),
78 "Strategy::Forced blueprint variant does not match the inputs operation",
79 );
80 let matmul = blueprint.matmul().clone();
81 (*algorithm, AcceleratedTileKind::Cmma, Some(matmul))
85 }
86 Strategy::Unit(strategy) => {
87 return unit::launch(*strategy, client, inputs, args, dtypes);
88 }
89 };
90
91 if inputs.operation() == ConvolutionOperation::BackwardData
93 && algorithm == ConvAlgorithm::SimpleAsyncTma
94 {
95 return Err(crate::kernels::backward_data::launch::unsupported_tma_error());
96 }
97
98 dispatch_routine::<N_SPATIAL>(
99 algorithm,
100 tile_kind,
101 forced_matmul,
102 client,
103 inputs,
104 args,
105 dtypes,
106 )
107}
108
109#[allow(clippy::result_large_err, clippy::too_many_arguments)]
112fn dispatch_routine<const N_SPATIAL: usize>(
113 algorithm: ConvAlgorithm,
114 tile_kind: AcceleratedTileKind,
115 forced_matmul: Option<BatchMatmulBlueprint>,
116 client: &Client,
117 inputs: ConvolutionInputs,
118 args: ConvolutionArgs<N_SPATIAL>,
119 dtypes: MatmulElems,
120) -> Result<(), ConvSetupError> {
121 let kind = tile_kind_to_dispatch(tile_kind);
122 match algorithm {
123 ConvAlgorithm::SimpleSyncCyclic => dispatch_inputs::<N_SPATIAL, SimpleSyncCyclicConv>(
124 client,
125 inputs,
126 args,
127 kind,
128 forced_matmul,
129 dtypes,
130 ),
131 ConvAlgorithm::SimpleSyncStrided => dispatch_inputs::<N_SPATIAL, SimpleSyncStridedConv>(
132 client,
133 inputs,
134 args,
135 kind,
136 forced_matmul,
137 dtypes,
138 ),
139 ConvAlgorithm::SimpleSyncTilewise => dispatch_inputs::<N_SPATIAL, SimpleSyncTilewiseConv>(
140 client,
141 inputs,
142 args,
143 kind,
144 forced_matmul,
145 dtypes,
146 ),
147 ConvAlgorithm::SimpleAsyncCyclic => dispatch_inputs::<N_SPATIAL, SimpleAsyncCyclicConv>(
148 client,
149 inputs,
150 args,
151 kind,
152 forced_matmul,
153 dtypes,
154 ),
155 ConvAlgorithm::SimpleAsyncStrided => dispatch_inputs::<N_SPATIAL, SimpleAsyncStridedConv>(
156 client,
157 inputs,
158 args,
159 kind,
160 forced_matmul,
161 dtypes,
162 ),
163 ConvAlgorithm::SimpleAsyncTma => dispatch_inputs::<N_SPATIAL, SimpleAsyncTmaConv>(
164 client,
165 inputs,
166 args,
167 kind,
168 forced_matmul,
169 dtypes,
170 ),
171 ConvAlgorithm::SpecializedAsyncCyclic => {
172 dispatch_inputs::<N_SPATIAL, SpecializedAsyncCyclicConv>(
173 client,
174 inputs,
175 args,
176 kind,
177 forced_matmul,
178 dtypes,
179 )
180 }
181 ConvAlgorithm::SpecializedAsyncStrided => {
182 dispatch_inputs::<N_SPATIAL, SpecializedAsyncStridedConv>(
183 client,
184 inputs,
185 args,
186 kind,
187 forced_matmul,
188 dtypes,
189 )
190 }
191 ConvAlgorithm::SpecializedTma => dispatch_inputs::<N_SPATIAL, SpecializedTmaConv>(
192 client,
193 inputs,
194 args,
195 kind,
196 forced_matmul,
197 dtypes,
198 ),
199 }
200}
201
202#[allow(clippy::result_large_err, clippy::too_many_arguments)]
208fn dispatch_inputs<const N_SPATIAL: usize, Rt: Routine<Blueprint = BatchMatmulBlueprint>>(
209 client: &Client,
210 inputs: ConvolutionInputs,
211 args: ConvolutionArgs<N_SPATIAL>,
212 tile_matmul: TileMatmulKind,
213 forced_matmul: Option<BatchMatmulBlueprint>,
214 dtypes: MatmulElems,
215) -> Result<(), ConvSetupError>
216where
217 Rt::Args: forward::args::ConcreteArgs<Rt::MatmulRoutine>
218 + backward_data::args::ConcreteArgs<Rt::MatmulRoutine>
219 + backward_weight::args::ConcreteArgs<Rt::MatmulRoutine>,
220 Rt::Strategy: TilingArgs,
221{
222 let blueprint_strategy = build_blueprint_strategy::<Rt>(tile_matmul, forced_matmul);
223
224 match inputs {
225 ConvolutionInputs::Forward {
226 input,
227 weight,
228 bias,
229 out,
230 } => forward::launch::launch_internal::<N_SPATIAL, Rt>(
231 client,
232 input,
233 weight,
234 bias,
235 out,
236 args,
237 &blueprint_strategy,
238 dtypes,
239 ),
240 ConvolutionInputs::BackwardData {
241 out_grad,
242 weights,
243 in_grad,
244 } => backward_data::launch::launch_internal::<N_SPATIAL, Rt>(
245 client,
246 out_grad,
247 weights,
248 in_grad,
249 args,
250 &blueprint_strategy,
251 dtypes,
252 ),
253 ConvolutionInputs::BackwardWeight {
254 input,
255 out_grad,
256 weight_grad,
257 } => backward_weight::launch::launch_internal::<N_SPATIAL, Rt>(
258 client,
259 input,
260 out_grad,
261 weight_grad,
262 args,
263 &blueprint_strategy,
264 dtypes,
265 ),
266 }
267}
268
269fn build_blueprint_strategy<Rt: Routine<Blueprint = BatchMatmulBlueprint>>(
273 tile_matmul: TileMatmulKind,
274 forced_matmul: Option<BatchMatmulBlueprint>,
275) -> BlueprintStrategy<Rt::MatmulRoutine>
276where
277 Rt::Strategy: TilingArgs,
278{
279 match forced_matmul {
280 Some(matmul) => BlueprintStrategy::Forced(matmul),
281 None => {
282 let mut s = <Rt::MatmulRoutine as cubek_std::legacy::Routine>::Strategy::default();
283 s.set_tile_matmul(tile_matmul);
284 BlueprintStrategy::Inferred(s)
285 }
286 }
287}