cubek_convolution/routines/
base.rs1use crate::components::{ConvolutionOperation, global::args::RuntimeArgs};
2use cubecl::{
3 prelude::*,
4 std::tensor::{into_contiguous_pitched, is_contiguous_pitched},
5};
6use cubek_matmul::{
7 definition::AvailableVectorSizes,
8 multi_level::{BatchMatmulRoutine as MatmulRoutine, args::MatmulArgs, definition::Blueprint},
9};
10use std::fmt::Display;
11
12pub trait Routine {
21 type Blueprint: Blueprint;
22 type Strategy: Default + Display + Clone;
23
24 type MatmulRoutine: MatmulRoutine<RuntimeArgs, Blueprint = Self::Blueprint, Strategy = Self::Strategy>;
25 type Args: MatmulArgs<Config = RuntimeArgs>;
26
27 const IS_SPECIALIZED: bool = false;
30
31 fn correct_layout(
32 client: &Client,
33 handle: TensorBinding,
34 dtype: ElemType,
35 operation: ConvolutionOperation,
36 ) -> Result<TensorBinding, LaunchError>;
37
38 fn filter_vector_sizes(vector_sizes: AvailableVectorSizes) -> AvailableVectorSizes {
39 vector_sizes
40 }
41}
42
43pub(crate) fn contiguous_pitched_layout(
44 client: &Client,
45 binding: TensorBinding,
46 dtype: ElemType,
47) -> Result<TensorBinding, LaunchError> {
48 let binding = if has_valid_layout(&binding) {
49 binding
50 } else {
51 into_contiguous_pitched(client, binding, dtype).binding()
52 };
53 Ok(binding)
54}
55
56fn has_valid_layout(binding: &TensorBinding) -> bool {
57 let rank = binding.shape.len();
58 let dim_c = rank - 1;
59 binding.strides[dim_c] == 1
60}
61
62const TMA_STRIDE_ALIGN: usize = 16;
63
64pub(crate) fn into_tensor_handle_tma(
65 client: &Client,
66 handle: TensorBinding,
67 dtype: ElemType,
68 operation: ConvolutionOperation,
69) -> Result<TensorBinding, LaunchError> {
70 let binding = if has_valid_layout_tma(&handle, dtype, operation) {
71 handle
72 } else {
73 into_contiguous_pitched(client, handle, dtype).binding()
74 };
75 Ok(binding)
76}
77
78pub(crate) fn has_valid_layout_tma(
79 binding: &TensorBinding,
80 dtype: ElemType,
81 operation: ConvolutionOperation,
82) -> bool {
83 let stride_align = TMA_STRIDE_ALIGN / dtype.size();
84 let rank = binding.shape.len();
85 let dim_c = rank - 1;
86
87 let aligned = binding.strides[..dim_c]
88 .iter()
89 .all(|stride| stride % stride_align == 0);
90
91 let valid_layout = binding.strides[dim_c] == 1;
92
93 let is_valid_wgrad = if operation == ConvolutionOperation::BackwardWeight {
94 is_contiguous_pitched(&binding.shape, &binding.strides)
95 } else {
96 true
97 };
98
99 valid_layout && aligned && is_valid_wgrad
100}