rudnn/convolution/components/global/read/strategy/
async_full_cyclic.rs1use ruda_kernel::dsl as kernel_dsl;
2use std::marker::PhantomData;
3
4use ruda_kernel::dsl::prelude::*;
5use ruda_kernel::library::tensor::layout::Layout;
6use ruda_kernel::library::tensor::layout::LayoutExpand;
7use ruda_kernel::dsl::ir::DeviceProperties;
8use ruda_kernel::dsl::prelude::barrier::Barrier;
9use rublas::kernel_ir::components::{
10 global::{
11 GlobalReaderConfig, PlaneFlowPartition,
12 memory::GlobalIterator,
13 multi_stage::LoadMaxRoundPlaneCount,
14 read::{
15 FullLoadingStrategy, LoadingJob, LoadingValidation, ReaderMode,
16 async_barrier::AsyncCopy,
17 async_full_cyclic::AsyncFullCyclicLoading as MatmulCyclicLoading, tiled::TiledLayout,
18 },
19 },
20 stage::{ContiguousTilingLayout, StridedStageFamily, StridedStageMemory, TilingOrder},
21};
22use rublas::kernel_ir::definition::{MatmulElems, MatmulProblem};
23use ruda_kernel::tiling::{InvalidConfigError, StageIdent, tile::Strided};
24
25use crate::convolution::components::global::{
26 args::RuntimeArgs,
27 read::strategy::async_copy::{ASYNC_COPY_WIDTH, async_copy_from},
28};
29
30#[derive(RudaType, Clone, Copy)]
31pub struct AsyncFullCyclicLoading<T: TilingOrder> {
34 #[ruda(comptime)]
35 _t: PhantomData<T>,
36}
37
38impl<TO: TilingOrder> LoadingValidation for AsyncFullCyclicLoading<TO> {
39 fn validate_with_config(
40 device_props: &DeviceProperties,
41 config: &GlobalReaderConfig,
42 ) -> Result<(), InvalidConfigError> {
43 MatmulCyclicLoading::<TO>::validate_with_config(device_props, config)
44 }
45
46 fn validate_with_problem(
47 problem: &MatmulProblem,
48 dtypes: &MatmulElems,
49 ident: StageIdent,
50 ) -> Result<(), InvalidConfigError> {
51 MatmulCyclicLoading::<TO>::validate_with_problem(problem, dtypes, ident)
52 }
53}
54
55impl<TO: TilingOrder> LoadMaxRoundPlaneCount for AsyncFullCyclicLoading<TO> {
56 fn max_round_plane_count(
57 elements_per_tile: u32,
58 tiles_per_stage: u32,
59 vector_size: VectorSize,
60 plane_dim: u32,
61 dtype: StorageType,
62 ) -> u32 {
63 MatmulCyclicLoading::<TO>::max_round_plane_count(
64 elements_per_tile,
65 tiles_per_stage,
66 vector_size,
67 plane_dim,
68 dtype,
69 )
70 }
71}
72
73#[ruda]
74impl<TO: TilingOrder> FullLoadingStrategy<RuntimeArgs> for AsyncFullCyclicLoading<TO> {
75 type TilingLayout = ContiguousTilingLayout<TO>;
76 type SyncStrategy = AsyncCopy;
77 type Job<EG: Numeric, NG: Size, ES: Numeric, NS: Size> = AsyncFullCyclicJob;
78 type Stage = StridedStageFamily;
79 type TileKind = Strided;
80
81 fn new_job<EG: Numeric, NG: Size, ES: Numeric, NS: Size>(
82 runtime_args: RuntimeArgs,
83 #[comptime] config: GlobalReaderConfig,
84 ) -> Self::Job<EG, NG, ES, NS> {
85 let type_size = ES::type_size_bits().comptime();
86 let vector_size = ASYNC_COPY_WIDTH / type_size as u32;
87 let tile_num_elements = config.smem_config.elements_per_tile();
88 let num_stage_elements = config.smem_config.elements_per_stage();
89
90 let num_stage_vectors = num_stage_elements.div_ceil(vector_size);
91 let total_units = config.loading_units_count();
92 let num_tasks_per_unit = num_stage_vectors.div_ceil(total_units);
93 let balanced_workload = num_stage_vectors.is_multiple_of(total_units);
94 let jump_length = total_units * vector_size;
95
96 let unit_id = PlaneFlowPartition::new(config.plane_flow_config.partition_rule)
97 .load_index(config.input_load_flow)
98 * config.plane_dim
99 + UNIT_POS_X;
100 let unit_position_base = unit_id * vector_size;
101
102 AsyncFullCyclicJob {
103 unit_position_base,
104 runtime_args,
105 num_tasks_per_unit,
106 tile_num_elements,
107 jump_length,
108 copy_vector_size: vector_size,
109 balanced_workload,
110 num_stage_elements,
111 reader_mode: config.reader_mode,
112 }
113 }
114}
115
116#[derive(RudaType, Clone)]
117pub struct AsyncFullCyclicJob {
118 unit_position_base: u32,
119 runtime_args: RuntimeArgs,
120
121 #[ruda(comptime)]
122 num_tasks_per_unit: u32,
123 #[ruda(comptime)]
124 tile_num_elements: u32,
125 #[ruda(comptime)]
126 jump_length: u32,
127 #[ruda(comptime)]
128 copy_vector_size: u32,
129 #[ruda(comptime)]
130 balanced_workload: bool,
131 #[ruda(comptime)]
132 num_stage_elements: u32,
133 #[ruda(comptime)]
134 reader_mode: ReaderMode,
135}
136
137#[ruda]
138impl<EG: Numeric, NG: Size, ES: Numeric, NS: Size, TO: TilingOrder>
139 LoadingJob<EG, NG, ES, NS, ContiguousTilingLayout<TO>, AsyncCopy> for AsyncFullCyclicJob
140{
141 type Stage = StridedStageFamily;
142
143 fn execute_task(
144 this: &mut Self,
145 #[comptime] task_id: u32,
146 global_iter: &GlobalIterator<Vector<EG, NG>>,
147 stage: &mut StridedStageMemory<ES, NS, ContiguousTilingLayout<TO>>,
148 _barrier: &mut Shared<Barrier>,
149 #[comptime] config: GlobalReaderConfig,
150 ) {
151 let unit_position = this.unit_position_base + task_id * this.jump_length;
152
153 #[allow(clippy::collapsible_else_if)]
154 if comptime!(this.reader_mode == ReaderMode::Strict || this.balanced_workload) {
155 copy_vector::<EG, NG, ES, NS, TO>(
156 this,
157 unit_position,
158 global_iter,
159 stage,
160 &this.runtime_args,
161 config,
162 );
163 } else {
164 if unit_position < this.num_stage_elements {
165 copy_vector::<EG, NG, ES, NS, TO>(
166 this,
167 unit_position,
168 global_iter,
169 stage,
170 &this.runtime_args,
171 config,
172 );
173 }
174 }
175 }
176
177 fn task_count(this: &Self) -> comptime_type!(u32) {
178 this.num_tasks_per_unit
179 }
180}
181
182#[ruda]
183pub(crate) fn copy_vector<EG: Numeric, NG: Size, ES: Numeric, NS: Size, TO: TilingOrder>(
184 job: &AsyncFullCyclicJob,
185 unit_position: u32,
186 global_iter: &GlobalIterator<Vector<EG, NG>>,
187 stage: &mut StridedStageMemory<ES, NS, ContiguousTilingLayout<TO>>,
188 runtime_args: &RuntimeArgs,
189 #[comptime] config: GlobalReaderConfig,
190) {
191 let nth_tile = unit_position / job.tile_num_elements;
192 let pos_within_tile = unit_position % job.tile_num_elements;
193
194 let layout = TiledLayout::new(config.stage_ident, config.smem_config);
195 let view = global_iter.view();
196
197 let tile = ContiguousTilingLayout::<TO>::to_x_y(nth_tile, config.smem_config);
198
199 let pos = layout.to_source_pos((tile, pos_within_tile));
200 let stage_offset = unit_position / stage.smem.vector_size() as u32;
201
202 async_copy_from(
203 view,
204 pos,
205 stage,
206 stage_offset,
207 runtime_args,
208 global_iter.offset(),
209 config,
210 job.copy_vector_size,
211 );
212}