cubek_matmul/components/global/read/reader/
full_reader.rs1use std::marker::PhantomData;
2
3use crate::components::global::multi_stage::JobExecutor;
4use crate::components::global::read::LoadingJob;
5use crate::components::global::read::LoadingValidation;
6use crate::components::global::read::StageBuffer;
7use crate::components::global::read::SyncStrategy;
8use crate::components::global::read::TaskCounter;
9use crate::components::global::{multi_stage::JobIterator, read::FullLoaderStage};
10use crate::components::stage::TilingLayout;
11use crate::components::{global::memory::GlobalIterator, stage::LoadStageFamily};
12use crate::components::{global::multi_stage::LoadMaxRoundPlaneCount, tile::io::TileKind};
13use crate::{components::global::GlobalReaderConfig, launch::RuntimeConfig};
14use cubecl::prelude::*;
15use cubecl::std::tensor::{View, layout::Coords2d};
16
17pub type SyncBarrier<S> = <S as SyncStrategy>::Barrier;
18
19#[cube]
20pub trait FullLoadingStrategy<RC: RuntimeConfig>:
22 'static + Send + Sync + Clone + LoadingValidation + LoadMaxRoundPlaneCount
23{
24 type TilingLayout: TilingLayout;
26 type SyncStrategy: SyncStrategy;
28 type Stage: LoadStageFamily<ReadOnly, TileKind = Self::TileKind>;
29 type TileKind: TileKind;
30
31 type Job<EG: Numeric, ES: Numeric>: LoadingJob<EG, ES, Self::TilingLayout, Self::SyncStrategy, Stage = Self::Stage>;
33
34 const SHOULD_CLEAR: bool = false;
35
36 fn new_job<EG: Numeric, ES: Numeric>(
38 config: RC,
39 #[comptime] line_size: LineSize,
40 #[comptime] config: GlobalReaderConfig,
41 ) -> Self::Job<EG, ES>;
42}
43
44#[derive(Clone, CubeType)]
45pub struct FullStageGlobalReader<
50 EG: Numeric,
51 ES: Numeric,
52 RC: RuntimeConfig,
53 L: FullLoadingStrategy<RC>,
54> {
55 global_iter: GlobalIterator<Line<EG>>,
56 runtime_config: RC,
57 stage: FullLoaderStage<RC, L, ES>,
58 loading_job: Option<L::Job<EG, ES>>,
59 #[cube(comptime)]
60 _phantom: PhantomData<L>,
61}
62
63#[cube]
64impl<EG: Numeric, ES: Numeric, RC: RuntimeConfig, L: FullLoadingStrategy<RC>>
65 FullStageGlobalReader<EG, ES, RC, L>
66{
67 pub fn new(
69 view: View<Line<EG>, Coords2d>,
70 runtime_config: RC,
71 k_step: u32,
72 #[comptime] config: GlobalReaderConfig,
73 ) -> Self {
74 let stage = L::Stage::create(128usize, config.smem_config);
77
78 let global_iter =
79 GlobalIterator::new(view, k_step, config.gmem_config.view_direction, false);
80
81 let loading_job = match config.precompute_job {
82 true => Option::new_Some(L::new_job::<EG, ES>(
83 runtime_config.clone(),
84 view.line_size(),
85 config,
86 )),
87 false => Option::new_None(),
88 };
89
90 FullStageGlobalReader::<EG, ES, RC, L> {
91 global_iter,
92 runtime_config,
93 stage,
94 loading_job,
95 _phantom: PhantomData::<L>,
96 }
97 }
98
99 pub fn stage(&self) -> FullLoaderStage<RC, L, ES> {
101 L::Stage::with_buffer_index(&self.stage, 0)
102 }
103
104 pub fn free_stage(self) {
106 L::Stage::free(&self.stage);
107 }
108
109 pub fn advance_view(&mut self) {
111 self.global_iter.advance();
112 }
113
114 pub fn load_stage(
116 &mut self,
117 barrier: &mut SyncBarrier<L::SyncStrategy>,
118 #[comptime] config: GlobalReaderConfig,
119 ) {
120 let mut loading_job = self.loading_job.clone().unwrap_or_else(|| {
121 L::new_job::<EG, ES>(
122 self.runtime_config.clone(),
123 self.global_iter.line_size(),
124 config,
125 )
126 });
127
128 let len = L::Job::task_count(&loading_job);
129
130 #[unroll]
131 for task_id in 0..len {
132 L::Job::<EG, ES>::execute_task(
133 &mut loading_job,
134 task_id,
135 &self.global_iter,
136 &mut self.stage,
137 barrier,
138 config,
139 );
140 }
141 }
142}
143
144#[cube]
145impl<EG: Numeric, ES: Numeric, RC: RuntimeConfig, L: FullLoadingStrategy<RC>>
146 JobExecutor<L::SyncStrategy> for FullStageGlobalReader<EG, ES, RC, L>
147{
148 type JobIterator = FullStageJobIterator<EG, ES, RC, L>;
149
150 fn create_job_iterator(
151 this: &Self,
152 #[comptime] _stage_buffer: StageBuffer,
153 #[comptime] config: GlobalReaderConfig,
154 ) -> Self::JobIterator {
155 let view = this.global_iter.view();
156 let job = this.loading_job.clone().unwrap_or_else(|| {
157 L::new_job::<EG, ES>(this.runtime_config.clone(), view.line_size(), config)
158 });
159
160 let num_tasks = L::Job::task_count(&job);
161
162 FullStageJobIterator::<EG, ES, RC, L> {
163 job,
164 num_tasks,
165 current: ComptimeCell::new(TaskCounter { counter: 0u32 }),
166 }
167 }
168
169 fn execute_task(
170 this: &mut Self,
171 job_iterator: &mut FullStageJobIterator<EG, ES, RC, L>,
172 barrier: &mut SyncBarrier<L::SyncStrategy>,
173 #[comptime] config: GlobalReaderConfig,
174 ) {
175 let task_id = job_iterator.current.read().counter.comptime();
176
177 L::Job::<EG, ES>::execute_task(
178 &mut job_iterator.job,
179 task_id,
180 &this.global_iter,
181 &mut this.stage,
182 barrier,
183 config,
184 );
185
186 job_iterator.current.store(TaskCounter {
187 counter: task_id + 1,
188 });
189 }
190
191 fn execute_all_remaining_tasks(
192 this: &mut Self,
193 job_iterator: &mut Self::JobIterator,
194 barrier: &mut SyncBarrier<L::SyncStrategy>,
195 #[comptime] config: GlobalReaderConfig,
196 ) {
197 let task_counter = job_iterator.current.read().counter;
198
199 #[unroll]
200 for task_id in task_counter..job_iterator.num_tasks {
201 L::Job::<EG, ES>::execute_task(
202 &mut job_iterator.job,
203 task_id,
204 &this.global_iter,
205 &mut this.stage,
206 barrier,
207 config,
208 );
209 }
210
211 job_iterator.current.store(TaskCounter {
212 counter: job_iterator.num_tasks,
213 });
214 }
215
216 fn execute_whole_job(
217 this: &mut Self,
218 barrier: &mut SyncBarrier<L::SyncStrategy>,
219 #[comptime] stage_buffer: StageBuffer,
220 #[comptime] config: GlobalReaderConfig,
221 ) {
222 Self::execute_all_remaining_tasks(
223 this,
224 &mut Self::create_job_iterator(this, stage_buffer, config),
225 barrier,
226 config,
227 );
228 }
229}
230
231#[derive(CubeType)]
232pub struct FullStageJobIterator<
234 EG: Numeric,
235 ES: Numeric,
236 RC: RuntimeConfig,
237 L: FullLoadingStrategy<RC>,
238> {
239 job: L::Job<EG, ES>,
240 #[cube(comptime)]
241 pub num_tasks: u32,
242 pub current: ComptimeCell<TaskCounter>,
243}
244
245#[cube]
246impl<EG: Numeric, ES: Numeric, RC: RuntimeConfig, L: FullLoadingStrategy<RC>> JobIterator
247 for FullStageJobIterator<EG, ES, RC, L>
248{
249 fn current(this: &Self) -> comptime_type!(u32) {
250 this.current.read().counter
251 }
252
253 fn num_tasks(this: &Self) -> comptime_type!(u32) {
254 this.num_tasks
255 }
256}