1use rayon::prelude::*;
2use rten_base::iter::SplitIterator;
3use rten_parallel::par_iter::ParIter;
4
5use super::{
6 AxisChunks, AxisChunksMut, AxisIter, AxisIterMut, InnerIter, InnerIterBase, InnerIterMut, Iter,
7 IterMut, LaneRanges, Lanes, LanesMut, Offsets, OffsetsKind,
8};
9use crate::Storage;
10use crate::layout::{Layout, MutLayout, RemoveDim};
11
12macro_rules! impl_parallel_iterator {
15 () => {
16 type Iter = ParIter<Self>;
17 type Item = <Self as Iterator>::Item;
18
19 fn into_par_iter(self) -> Self::Iter {
20 self.into()
21 }
22 };
23}
24
25impl SplitIterator for Offsets {
26 fn split_at(self, index: usize) -> (Self, Self) {
27 assert!(index <= self.len());
28 let (left_kind, right_kind) = match self.base {
29 OffsetsKind::Range(r) => {
30 let left = r.start..r.start + index;
31 let right = r.start + index..r.end;
32 (OffsetsKind::Range(left), OffsetsKind::Range(right))
33 }
34 OffsetsKind::Indexing(base) => {
35 let (left, right) = base.split_at(index);
36 (OffsetsKind::Indexing(left), OffsetsKind::Indexing(right))
37 }
38 };
39 (Offsets { base: left_kind }, Offsets { base: right_kind })
40 }
41}
42
43impl<L: Layout + Clone> SplitIterator for InnerIterBase<L> {
44 fn split_at(self, index: usize) -> (Self, Self) {
45 let (left_offsets, right_offsets) = self.outer_offsets.split_at(index);
46 let left = Self {
47 outer_offsets: left_offsets,
48 inner_layout: self.inner_layout.clone(),
49 inner_data_len: self.inner_data_len,
50 };
51 let right = Self {
52 outer_offsets: right_offsets,
53 inner_layout: self.inner_layout,
54 inner_data_len: self.inner_data_len,
55 };
56 (left, right)
57 }
58}
59
60impl<'a, T, L: MutLayout + Send + Sync> SplitIterator for InnerIter<'a, T, L> {
61 fn split_at(self, index: usize) -> (Self, Self) {
62 let (left_base, right_base) = self.base.split_at(index);
63 let left = Self {
64 base: left_base,
65 data: self.data,
66 };
67 let right = Self {
68 base: right_base,
69 data: self.data,
70 };
71 (left, right)
72 }
73}
74
75impl<'a, T, L: MutLayout + Send + Sync> IntoParallelIterator for InnerIter<'a, T, L> {
76 impl_parallel_iterator!();
77}
78
79impl<'a, T, L: MutLayout + Send + Sync> SplitIterator for InnerIterMut<'a, T, L> {
80 fn split_at(self, index: usize) -> (Self, Self) {
81 let (left_base, right_base) = self.base.split_at(index);
82 let len = self.data.len();
83
84 let (left_data, right_data) = self.data.split_mut(0..len, 0..len);
88
89 let left = Self {
90 base: left_base,
91 data: left_data,
92 };
93 let right = Self {
94 base: right_base,
95 data: right_data,
96 };
97 (left, right)
98 }
99}
100
101impl<'a, T, L: MutLayout + Send + Sync> IntoParallelIterator for InnerIterMut<'a, T, L> {
102 impl_parallel_iterator!();
103}
104
105impl<'a, T, L: MutLayout + RemoveDim> SplitIterator for AxisIter<'a, T, L> {
106 fn split_at(self, index: usize) -> (Self, Self) {
107 let (left_view, right_view) = self.view.split_at(self.axis, index);
108 let left = AxisIter::new(&left_view, self.axis);
109 let right = AxisIter::new(&right_view, self.axis);
110 (left, right)
111 }
112}
113
114impl<'a, T, L: MutLayout + RemoveDim + Send> IntoParallelIterator for AxisIter<'a, T, L>
115where
116 <L as RemoveDim>::Output: Send,
117{
118 impl_parallel_iterator!();
119}
120
121impl<'a, T, L: MutLayout + RemoveDim> SplitIterator for AxisIterMut<'a, T, L> {
122 fn split_at(self, index: usize) -> (Self, Self) {
123 let (left_view, right_view) = self.view.split_at_mut(self.axis, index);
124 let left = AxisIterMut::new(left_view, self.axis);
125 let right = AxisIterMut::new(right_view, self.axis);
126 (left, right)
127 }
128}
129
130impl<'a, T, L: MutLayout + RemoveDim + Send> IntoParallelIterator for AxisIterMut<'a, T, L>
131where
132 <L as RemoveDim>::Output: Send,
133{
134 impl_parallel_iterator!();
135}
136
137impl<'a, T, L: MutLayout> SplitIterator for AxisChunks<'a, T, L> {
138 fn split_at(mut self, index: usize) -> (Self, Self) {
139 let (left_remainder, right_remainder) = if let Some(remainder) = self.remainder.take() {
140 let (l, r) = remainder.split_at(self.axis, self.chunk_size * index);
141 (Some(l), Some(r))
142 } else {
143 (None, None)
144 };
145
146 let left = AxisChunks {
147 remainder: left_remainder,
148 axis: self.axis,
149 chunk_size: self.chunk_size,
150 };
151 let right = AxisChunks {
152 remainder: right_remainder,
153 axis: self.axis,
154 chunk_size: self.chunk_size,
155 };
156
157 (left, right)
158 }
159}
160
161impl<'a, T, L: MutLayout + Send> IntoParallelIterator for AxisChunks<'a, T, L> {
162 impl_parallel_iterator!();
163}
164
165impl<'a, T, L: MutLayout> SplitIterator for AxisChunksMut<'a, T, L> {
166 fn split_at(mut self, index: usize) -> (Self, Self) {
167 let (left_remainder, right_remainder) = if let Some(remainder) = self.remainder.take() {
168 let (l, r) = remainder.split_at_mut(self.axis, self.chunk_size * index);
169 (Some(l), Some(r))
170 } else {
171 (None, None)
172 };
173
174 let left = Self {
175 remainder: left_remainder,
176 axis: self.axis,
177 chunk_size: self.chunk_size,
178 };
179 let right = Self {
180 remainder: right_remainder,
181 axis: self.axis,
182 chunk_size: self.chunk_size,
183 };
184
185 (left, right)
186 }
187}
188
189impl<'a, T, L: MutLayout + Send> IntoParallelIterator for AxisChunksMut<'a, T, L> {
190 impl_parallel_iterator!();
191}
192
193impl<'a, T> SplitIterator for Iter<'a, T> {
194 fn split_at(self, index: usize) -> (Self, Self) {
195 let (left_offsets, right_offsets) = self.offsets.split_at(index);
196 let left = Self {
197 offsets: left_offsets,
198 data: self.data,
199 };
200 let right = Self {
201 offsets: right_offsets,
202 data: self.data,
203 };
204 (left, right)
205 }
206}
207
208impl<'a, T: Sync> IntoParallelIterator for Iter<'a, T> {
209 impl_parallel_iterator!();
210}
211
212impl<'a, T> SplitIterator for IterMut<'a, T> {
213 fn split_at(self, index: usize) -> (Self, Self) {
214 let (left_offsets, right_offsets) = self.offsets.split_at(index);
215 let len = self.data.len();
216 let (left_data, right_data) = self.data.split_mut(0..len, 0..len);
217 let left = Self {
218 offsets: left_offsets,
219 data: left_data,
220 };
221 let right = Self {
222 offsets: right_offsets,
223 data: right_data,
224 };
225 (left, right)
226 }
227}
228
229impl<'a, T: Sync + Send> IntoParallelIterator for IterMut<'a, T> {
230 impl_parallel_iterator!();
231}
232
233impl SplitIterator for LaneRanges {
234 fn split_at(self, index: usize) -> (Self, Self) {
235 let (left_offsets, right_offsets) = self.offsets.split_at(index);
236 let left = LaneRanges {
237 offsets: left_offsets,
238 dim_size: self.dim_size,
239 dim_stride: self.dim_stride,
240 };
241 let right = LaneRanges {
242 offsets: right_offsets,
243 dim_size: self.dim_size,
244 dim_stride: self.dim_stride,
245 };
246 (left, right)
247 }
248}
249
250impl<'a, T> SplitIterator for Lanes<'a, T> {
251 fn split_at(self, index: usize) -> (Self, Self) {
252 let (left_range, right_range) = self.ranges.split_at(index);
253
254 let left = Lanes {
255 data: self.data,
256 ranges: left_range,
257 lane_layout: self.lane_layout,
258 };
259 let right = Lanes {
260 data: self.data,
261 ranges: right_range,
262 lane_layout: self.lane_layout,
263 };
264
265 (left, right)
266 }
267}
268
269impl<'a, T: Sync + Send> IntoParallelIterator for Lanes<'a, T> {
270 impl_parallel_iterator!();
271}
272
273impl<'a, T> SplitIterator for LanesMut<'a, T> {
274 fn split_at(self, index: usize) -> (Self, Self) {
275 let (left_range, right_range) = self.ranges.split_at(index);
276 let len = self.data.len();
277
278 let (left_data, right_data) = self.data.split_mut(0..len, 0..len);
281
282 let left = Self {
283 data: left_data,
284 ranges: left_range,
285 lane_layout: self.lane_layout,
286 };
287 let right = Self {
288 data: right_data,
289 ranges: right_range,
290 lane_layout: self.lane_layout,
291 };
292
293 (left, right)
294 }
295}
296
297impl<T: Sync + Send> IntoParallelIterator for LanesMut<'_, T> {
298 impl_parallel_iterator!();
299}
300
301#[cfg(test)]
302mod tests {
303 use rayon::prelude::*;
304
305 use crate::rng::XorShiftRng;
306 use crate::{AsView, Tensor};
307
308 macro_rules! test_parallel_iterator {
315 ($x:ident, $iter:expr) => {
316 let mut rng = XorShiftRng::new(1234);
317 let $x = Tensor::<f32>::rand(&[4, 8, 16, 32], &mut rng);
318 let serial: Vec<_> = $iter.collect();
319 let parallel: Vec<_> = $iter.into_par_iter().collect();
320 assert_eq!(serial, parallel);
321 };
322 }
323
324 macro_rules! test_parallel_iterator_mut {
327 ($x:ident, $iter:expr, $item_sum:expr) => {
328 let mut rng = XorShiftRng::new(1234);
329
330 let mut $x =
334 Tensor::<i32>::from_simple_fn(&[4, 8, 16, 32], || (rng.next_f32() * 100.) as i32);
335 let serial: i32 = $iter.map($item_sum).sum();
336 let parallel: i32 = $iter.into_par_iter().map($item_sum).sum();
337
338 assert_eq!(serial, parallel);
339 };
340 }
341
342 macro_rules! test_parallel_iterator_flatten {
347 ($x:ident, $iter:expr) => {
348 let mut rng = XorShiftRng::new(1234);
349 let $x = Tensor::<f32>::rand(&[4, 8, 16, 32], &mut rng);
350
351 let serial: Vec<_> = $iter.collect();
352 let parallel: Vec<_> = $iter.into_par_iter().collect();
353
354 let serial_items: Vec<f32> = serial.into_iter().flatten().copied().collect();
355 let parallel_items: Vec<f32> = parallel.into_iter().flatten().copied().collect();
356 assert_eq!(serial_items, parallel_items);
357 };
358 }
359
360 #[test]
364 #[cfg_attr(miri, ignore)]
365 fn test_inner_iter_parallel() {
366 test_parallel_iterator!(x, x.inner_iter::<2>());
367 }
368
369 #[test]
370 #[cfg_attr(miri, ignore)]
371 fn test_inner_iter_mut_parallel() {
372 test_parallel_iterator_mut!(x, x.inner_iter_mut::<2>(), |x| x.iter().sum::<i32>());
373 }
374
375 #[test]
376 #[cfg_attr(miri, ignore)]
377 fn test_iter_parallel() {
378 test_parallel_iterator!(x, x.iter());
379 }
380
381 #[test]
382 #[cfg_attr(miri, ignore)]
383 fn test_iter_mut_parallel() {
384 test_parallel_iterator_mut!(x, x.iter_mut(), |x| *x);
385 }
386
387 #[test]
388 #[cfg_attr(miri, ignore)]
389 fn test_axis_chunks_parallel() {
390 test_parallel_iterator!(x, x.axis_chunks(0, 2));
391 }
392
393 #[test]
394 #[cfg_attr(miri, ignore)]
395 fn test_axis_chunks_mut_parallel() {
396 test_parallel_iterator_mut!(x, x.axis_chunks_mut(0, 2), |x| x.iter().sum::<i32>());
397 }
398
399 #[test]
400 #[cfg_attr(miri, ignore)]
401 fn test_axis_iter_parallel() {
402 test_parallel_iterator!(x, x.axis_iter(0));
403 }
404
405 #[test]
406 #[cfg_attr(miri, ignore)]
407 fn test_axis_iter_mut_parallel() {
408 test_parallel_iterator_mut!(x, x.axis_iter_mut(0), |x| x.iter().sum::<i32>());
409 }
410
411 #[test]
412 #[cfg_attr(miri, ignore)]
413 fn test_lanes_parallel() {
414 test_parallel_iterator_flatten!(x, x.lanes(0));
415 }
416
417 #[test]
418 #[cfg_attr(miri, ignore)]
419 fn test_lanes_mut_parallel() {
420 test_parallel_iterator_mut!(x, x.lanes_mut(0), |x| x.map(|x| *x).sum::<i32>());
421 }
422}