Skip to main content

rudnn/convolution/launch/
base.rs

1//! Unified `launch_ref` entry point for the convolution kernel family.
2//!
3//! Picks the right `Routine` impl from `ConvAlgorithm`, threads the
4//! `Strategy` (`Specific` / `Forced`) into a matmul `BlueprintStrategy`, and
5//! dispatches to the per-operation helper based on `ConvolutionInputs`.
6
7use ruda_kernel::dsl as kernel_dsl;
8use ruda_kernel::dsl::Runtime;
9use ruda_kernel::dsl::client::ComputeClient;
10use rublas::kernel_ir::{
11    components::tile::TileMatmulKind,
12    definition::{MatmulElems, TilingBlueprint},
13    routines::{BlueprintStrategy, Routine as MatmulRoutine, TilingArgs},
14};
15
16use crate::convolution::components::ConvolutionOperation;
17use crate::convolution::definition::ConvBlueprint;
18
19fn blueprint_operation(blueprint: &ConvBlueprint) -> ConvolutionOperation {
20    match blueprint {
21        ConvBlueprint::Forward(_) => ConvolutionOperation::Forward,
22        ConvBlueprint::BackwardData(_) => ConvolutionOperation::BackwardData,
23        ConvBlueprint::BackwardWeight(_) => ConvolutionOperation::BackwardWeight,
24    }
25}
26
27use crate::convolution::{
28    components::{ConvSetupError, global::args::RuntimeArgs},
29    kernels::{backward_data, backward_weight, forward},
30    launch::{
31        ConvAlgorithm, ConvolutionArgs, ConvolutionInputs, Strategy, strategy::AcceleratedTileKind,
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
45/// Map `AcceleratedTileKind` → matmul's `TileMatmulKind`.
46pub(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/// The single public convolution entry point.
54///
55/// Routes the `inputs` (whose discriminant is the operation) and `strategy`
56/// (algorithm + tile-matmul kind, optionally a forced blueprint) into the right
57/// generic `Routine` and per-operation launch helper.
58#[allow(clippy::result_large_err)]
59pub fn launch_ref<R: Runtime, const N_SPATIAL: usize>(
60    strategy: &Strategy,
61    client: &ComputeClient<R>,
62    inputs: ConvolutionInputs<R>,
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            // For Forced, tile_kind is encoded inside the matmul blueprint, so
82            // the explicit tile_kind here is unused; we pass Cmma as a benign
83            // default (it gets overwritten by the forced blueprint).
84            (*algorithm, AcceleratedTileKind::Cmma, Some(matmul))
85        }
86    };
87
88    // Backward-data does not currently support the TMA reading strategy.
89    if inputs.operation() == ConvolutionOperation::BackwardData
90        && algorithm == ConvAlgorithm::SimpleAsyncTma
91    {
92        return Err(crate::convolution::kernels::backward_data::launch::unsupported_tma_error());
93    }
94
95    dispatch_routine::<R, N_SPATIAL>(
96        algorithm,
97        tile_kind,
98        forced_matmul,
99        client,
100        inputs,
101        args,
102        dtypes,
103    )
104}
105
106/// Dispatch on `ConvAlgorithm` to instantiate the right concrete `Routine`
107/// generic, then forward to the per-operation helper.
108#[allow(clippy::result_large_err, clippy::too_many_arguments)]
109fn dispatch_routine<R: Runtime, const N_SPATIAL: usize>(
110    algorithm: ConvAlgorithm,
111    tile_kind: AcceleratedTileKind,
112    forced_matmul: Option<TilingBlueprint>,
113    client: &ComputeClient<R>,
114    inputs: ConvolutionInputs<R>,
115    args: ConvolutionArgs<N_SPATIAL>,
116    dtypes: MatmulElems,
117) -> Result<(), ConvSetupError> {
118    let kind = tile_kind_to_dispatch(tile_kind);
119    match algorithm {
120        ConvAlgorithm::SimpleSyncCyclic => dispatch_inputs::<R, N_SPATIAL, SimpleSyncCyclicConv>(
121            client,
122            inputs,
123            args,
124            kind,
125            forced_matmul,
126            dtypes,
127        ),
128        ConvAlgorithm::SimpleSyncStrided => dispatch_inputs::<R, N_SPATIAL, SimpleSyncStridedConv>(
129            client,
130            inputs,
131            args,
132            kind,
133            forced_matmul,
134            dtypes,
135        ),
136        ConvAlgorithm::SimpleSyncTilewise => {
137            dispatch_inputs::<R, N_SPATIAL, SimpleSyncTilewiseConv>(
138                client,
139                inputs,
140                args,
141                kind,
142                forced_matmul,
143                dtypes,
144            )
145        }
146        ConvAlgorithm::SimpleAsyncCyclic => dispatch_inputs::<R, N_SPATIAL, SimpleAsyncCyclicConv>(
147            client,
148            inputs,
149            args,
150            kind,
151            forced_matmul,
152            dtypes,
153        ),
154        ConvAlgorithm::SimpleAsyncStrided => {
155            dispatch_inputs::<R, N_SPATIAL, SimpleAsyncStridedConv>(
156                client,
157                inputs,
158                args,
159                kind,
160                forced_matmul,
161                dtypes,
162            )
163        }
164        ConvAlgorithm::SimpleAsyncTma => dispatch_inputs::<R, N_SPATIAL, SimpleAsyncTmaConv>(
165            client,
166            inputs,
167            args,
168            kind,
169            forced_matmul,
170            dtypes,
171        ),
172        ConvAlgorithm::SpecializedAsyncCyclic => {
173            dispatch_inputs::<R, N_SPATIAL, SpecializedAsyncCyclicConv>(
174                client,
175                inputs,
176                args,
177                kind,
178                forced_matmul,
179                dtypes,
180            )
181        }
182        ConvAlgorithm::SpecializedAsyncStrided => {
183            dispatch_inputs::<R, N_SPATIAL, SpecializedAsyncStridedConv>(
184                client,
185                inputs,
186                args,
187                kind,
188                forced_matmul,
189                dtypes,
190            )
191        }
192        ConvAlgorithm::SpecializedTma => dispatch_inputs::<R, N_SPATIAL, SpecializedTmaConv>(
193            client,
194            inputs,
195            args,
196            kind,
197            forced_matmul,
198            dtypes,
199        ),
200    }
201}
202
203/// Branch on operation and forward to the per-op launcher.
204///
205/// All three per-op `ConcreteArgs` traits share the same name and the same
206/// blanket impls on `TensorArgs<RuntimeArgs>` / `TensorMapArgs<RuntimeArgs>`,
207/// so the where clause simply requires an impl per operation.
208#[allow(clippy::result_large_err, clippy::too_many_arguments)]
209fn dispatch_inputs<R: Runtime, const N_SPATIAL: usize, Rt: Routine<Blueprint = TilingBlueprint>>(
210    client: &ComputeClient<R>,
211    inputs: ConvolutionInputs<R>,
212    args: ConvolutionArgs<N_SPATIAL>,
213    tile_matmul: TileMatmulKind,
214    forced_matmul: Option<TilingBlueprint>,
215    dtypes: MatmulElems,
216) -> Result<(), ConvSetupError>
217where
218    Rt::Args: forward::args::ConcreteArgs<Rt::MatmulRoutine>
219        + backward_data::args::ConcreteArgs<Rt::MatmulRoutine>
220        + backward_weight::args::ConcreteArgs<Rt::MatmulRoutine>,
221    Rt::Strategy: TilingArgs,
222{
223    let blueprint_strategy = build_blueprint_strategy::<Rt>(tile_matmul, forced_matmul);
224
225    match inputs {
226        ConvolutionInputs::Forward {
227            input,
228            weight,
229            bias,
230            out,
231        } => forward::launch::launch_internal::<R, N_SPATIAL, Rt>(
232            client,
233            input,
234            weight,
235            bias,
236            out,
237            args,
238            &blueprint_strategy,
239            dtypes,
240        ),
241        ConvolutionInputs::BackwardData {
242            out_grad,
243            weights,
244            in_grad,
245        } => backward_data::launch::launch_internal::<R, N_SPATIAL, Rt>(
246            client,
247            out_grad,
248            weights,
249            in_grad,
250            args,
251            &blueprint_strategy,
252            dtypes,
253        ),
254        ConvolutionInputs::BackwardWeight {
255            input,
256            out_grad,
257            weight_grad,
258        } => backward_weight::launch::launch_internal::<R, N_SPATIAL, Rt>(
259            client,
260            input,
261            out_grad,
262            weight_grad,
263            args,
264            &blueprint_strategy,
265            dtypes,
266        ),
267    }
268}
269
270/// Build a matmul `BlueprintStrategy` from either a forced `TilingBlueprint`
271/// (extracted from `ConvBlueprint`) or an `Inferred` strategy stamped with the
272/// requested tile-matmul kind.
273fn build_blueprint_strategy<Rt: Routine<Blueprint = TilingBlueprint>>(
274    tile_matmul: TileMatmulKind,
275    forced_matmul: Option<TilingBlueprint>,
276) -> BlueprintStrategy<RuntimeArgs, Rt::MatmulRoutine>
277where
278    Rt::Strategy: TilingArgs,
279{
280    match forced_matmul {
281        Some(matmul) => BlueprintStrategy::Forced(matmul),
282        None => {
283            let mut s = <Rt::MatmulRoutine as MatmulRoutine<RuntimeArgs>>::Strategy::default();
284            s.set_tile_matmul(tile_matmul);
285            BlueprintStrategy::Inferred(s)
286        }
287    }
288}