1use std::marker::ConstParamTy;
2
3#[cfg(feature = "rayon")]
4use rayon::prelude::*;
5
6use crate::functor::ForFunctor;
7
8#[derive(ConstParamTy, Debug, Default, Clone, Copy, PartialEq, Eq)]
14pub enum Schedule {
15 #[default]
16 Static,
19 Dynamic,
22}
23
24#[derive(ConstParamTy, Debug, Default, Clone, Copy, PartialEq, Eq)]
31pub enum ExecutionSpace {
32 #[default]
33 Serial,
35 DeviceCPU,
38 DeviceGPU,
40}
41
42pub(crate) trait ExecutionPolicy
45where
46 Self: Sized,
47{
48 type KernelArgType;
49
50 fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, functor: F);
51
52 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, functor: F);
53
54 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, functor: F);
55}
56
57pub struct TeamHandle {
58 _league_rank: usize,
59 _team_rank: usize,
60 _team_size: usize,
61}
62
63pub struct Range(pub usize);
64pub struct MDRange<const N: usize>(pub [usize; N]);
65
66pub struct TeamPolicy(pub usize, pub usize, pub usize);
67pub struct PerTeam;
68pub struct PerThread;
69
70pub struct TeamThreadRange(pub TeamHandle, pub usize);
71pub struct TeamThreadMDRange<const N: usize>(pub TeamHandle, pub [usize; N]);
72
73pub struct TeamVectorRange(pub TeamHandle, pub usize);
74pub struct TeamVectorMDRange<const N: usize>(pub TeamHandle, pub [usize; N]);
75
76pub struct ThreadVectorRange(pub TeamHandle, pub usize);
77pub struct ThreadVectorMDRange<const N: usize>(pub TeamHandle, pub [usize; N]);
78
79impl ExecutionPolicy for Range {
80 type KernelArgType = usize;
81
82 fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, functor: F) {
83 let _ = SCHEDULE;
84 let Range(n) = self;
85
86 (0..n).for_each(|i| functor.execute(i));
87 }
88
89 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, functor: F) {
90 let Range(n) = self;
91
92 let n_threads = 4; match SCHEDULE {
95 #[cfg(not(feature = "rayon"))]
96 Schedule::Static => {
97 let chunk_size = n / n_threads + 1;
98
99 std::thread::scope(|s| {
100 let mut handles = Vec::with_capacity(n_threads);
101 let f = &functor;
102 let blocks = (0..n_threads)
103 .map(|tid| tid * chunk_size..(tid * chunk_size + chunk_size).min(n));
104
105 for b in blocks {
106 let h = s.spawn(move || {
107 b.into_iter().for_each(|i| f.execute(i));
108 });
109 handles.push(h);
110 }
111
112 for h in handles {
113 h.join().unwrap();
114 }
115 });
116 }
117 #[cfg(not(feature = "rayon"))]
118 Schedule::Dynamic => {
119 unimplemented!("E: Dynamic dispatch isn't supported without rayon");
120 }
121 #[cfg(feature = "rayon")]
122 Schedule::Static => {
123 let chunk_size = n / n_threads + 1;
124
125 (0..n_threads)
127 .into_par_iter()
128 .map(|tid| tid * chunk_size..(tid * chunk_size + chunk_size).min(n))
129 .for_each(|b| {
130 b.into_iter().for_each(|i| functor.execute(i));
131 });
132 }
133 #[cfg(feature = "rayon")]
134 Schedule::Dynamic => {
135 (0..n).into_par_iter().for_each(|i| functor.execute(i));
136 }
137 }
138 }
139
140 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
141 todo!()
142 }
143}
144impl<const N: usize> ExecutionPolicy for MDRange<N> {
145 type KernelArgType = [usize; N];
146
147 fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
148 todo!()
149 }
150
151 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
152 todo!()
153 }
154
155 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
156 todo!()
157 }
158}
159
160impl ExecutionPolicy for TeamPolicy {
161 type KernelArgType = TeamHandle;
162
163 fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
164 todo!()
165 }
166
167 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
168 todo!()
169 }
170
171 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
172 todo!()
173 }
174}
175impl ExecutionPolicy for PerTeam {
176 type KernelArgType = usize; fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
179 todo!()
180 }
181
182 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
183 todo!()
184 }
185
186 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
187 todo!()
188 }
189}
190impl ExecutionPolicy for PerThread {
191 type KernelArgType = usize; fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
194 todo!()
195 }
196
197 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
198 todo!()
199 }
200
201 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
202 todo!()
203 }
204}
205
206impl ExecutionPolicy for TeamThreadRange {
207 type KernelArgType = usize;
208
209 fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
210 todo!()
211 }
212
213 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
214 todo!()
215 }
216
217 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
218 todo!()
219 }
220}
221impl<const N: usize> ExecutionPolicy for TeamThreadMDRange<N> {
222 type KernelArgType = usize; fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
225 todo!()
226 }
227
228 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
229 todo!()
230 }
231
232 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
233 todo!()
234 }
235}
236
237impl ExecutionPolicy for ThreadVectorRange {
238 type KernelArgType = usize;
239
240 fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
241 todo!()
242 }
243
244 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
245 todo!()
246 }
247
248 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
249 todo!()
250 }
251}
252impl<const N: usize> ExecutionPolicy for ThreadVectorMDRange<N> {
253 type KernelArgType = usize; fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
256 todo!()
257 }
258
259 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
260 todo!()
261 }
262
263 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
264 todo!()
265 }
266}
267
268impl ExecutionPolicy for TeamVectorRange {
269 type KernelArgType = usize;
270
271 fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
272 todo!()
273 }
274
275 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
276 todo!()
277 }
278
279 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
280 todo!()
281 }
282}
283impl<const N: usize> ExecutionPolicy for TeamVectorMDRange<N> {
284 type KernelArgType = usize; fn dispatch_seq<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
287 todo!()
288 }
289
290 fn dispatch_cpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
291 todo!()
292 }
293
294 fn dispatch_gpu<const SCHEDULE: Schedule, F: ForFunctor<Self>>(self, _functor: F) {
295 todo!()
296 }
297}
298
299impl From<usize> for Range {
300 fn from(value: usize) -> Self {
301 Self(value)
302 }
303}
304
305impl<const N: usize> From<[usize; N]> for MDRange<N> {
306 fn from(value: [usize; N]) -> Self {
307 Self(value)
308 }
309}