rudnn/convolution/routines/
base.rs1use ruda_kernel::dsl as kernel_dsl;
2use crate::convolution::components::{ConvolutionOperation, global::args::RuntimeArgs};
3use ruda_kernel::dsl::prelude::*;
4use ruda_kernel::dsl::{CompilationError, backtrace::BackTrace, ir::features::Tma};
5use ruda_kernel::library::tensor::into_contiguous_pitched;
6use ruda_kernel::library::tensor::is_contiguous_pitched;
7use rublas::kernel_ir::{
8 definition::{AvailableVectorSizes, Blueprint},
9 launch::MatmulArgs,
10 routines::Routine as MatmulRoutine,
11};
12use std::fmt::Display;
13
14pub trait Routine {
23 type Blueprint: Blueprint;
24 type Strategy: Default + Display + Clone;
25
26 type MatmulRoutine: MatmulRoutine<RuntimeArgs, Blueprint = Self::Blueprint, Strategy = Self::Strategy>;
27 type Args: MatmulArgs<Config = RuntimeArgs>;
28
29 const IS_SPECIALIZED: bool = false;
32
33 fn correct_layout<R: Runtime>(
34 client: &ComputeClient<R>,
35 handle: TensorBinding<R>,
36 dtype: StorageType,
37 operation: ConvolutionOperation,
38 ) -> Result<TensorBinding<R>, LaunchError>;
39
40 fn filter_vector_sizes(vector_sizes: AvailableVectorSizes) -> AvailableVectorSizes {
41 vector_sizes
42 }
43}
44
45pub(crate) fn contiguous_pitched_layout<R: Runtime>(
46 client: &ComputeClient<R>,
47 binding: TensorBinding<R>,
48 dtype: StorageType,
49) -> Result<TensorBinding<R>, LaunchError> {
50 let binding = if has_valid_layout(&binding) {
51 binding
52 } else {
53 into_contiguous_pitched(client, binding, dtype).binding()
54 };
55 Ok(binding)
56}
57
58fn has_valid_layout<R: Runtime>(binding: &TensorBinding<R>) -> bool {
59 let rank = binding.shape.len();
60 let dim_c = rank - 1;
61 binding.strides[dim_c] == 1
62}
63
64const TMA_STRIDE_ALIGN: usize = 16;
65
66pub(crate) fn into_tensor_handle_tma<R: Runtime>(
67 client: &ComputeClient<R>,
68 handle: TensorBinding<R>,
69 dtype: StorageType,
70 operation: ConvolutionOperation,
71) -> Result<TensorBinding<R>, LaunchError> {
72 if !client.properties().features.tma.contains(Tma::Base) {
73 return Err(CompilationError::UnsupportedInstruction {
74 reason: "TMA convolution requires tensor-map support on this device".into(),
75 backtrace: BackTrace::capture(),
76 }.into());
77 }
78 let binding = if has_valid_layout_tma(&handle, dtype, operation) {
79 handle
80 } else {
81 into_contiguous_pitched(client, handle, dtype).binding()
82 };
83 Ok(binding)
84}
85
86pub(crate) fn has_valid_layout_tma<R: Runtime>(
87 binding: &TensorBinding<R>,
88 dtype: StorageType,
89 operation: ConvolutionOperation,
90) -> bool {
91 let stride_align = TMA_STRIDE_ALIGN / dtype.size();
92 let rank = binding.shape.len();
93 let dim_c = rank - 1;
94
95 let aligned = binding.strides[..dim_c]
96 .iter()
97 .all(|stride| stride % stride_align == 0);
98
99 let valid_layout = binding.strides[dim_c] == 1;
100
101 let is_valid_wgrad = if operation == ConvolutionOperation::BackwardWeight {
102 is_contiguous_pitched(&binding.shape, &binding.strides)
103 } else {
104 true
105 };
106
107 valid_layout && aligned && is_valid_wgrad
108}