orx_parallel/iter/recursive/rec_par_iter.rs
1use crate::{
2 ParIter, ParallelRunner,
3 computational_variants::{Par, ParMap, ParXap},
4 generic_values::{TransformableValues, runner_results::Infallible},
5};
6use alloc::vec::Vec;
7use orx_concurrent_iter::{IntoConcurrentIter, implementations::ConIterVec};
8use orx_concurrent_recursive_iter::{ConcurrentRecursiveIter, Queue};
9
10type Rec<T, E> = ConcurrentRecursiveIter<T, E>;
11
12impl<E, T, R> Par<Rec<T, E>, R>
13where
14 T: Send + Sync,
15 E: Fn(&T, &Queue<T>) + Sync,
16 R: ParallelRunner + Clone,
17{
18 /// Even with exact length, a recursive parallel iterator is much more dynamic than a flat parallel
19 /// iterator. This dynamic nature of shrinking and growing concurrently requires a greater parallelization
20 /// overhead. An alternative approach is to eagerly discover all tasks and then perform the parallel
21 /// computation over the flattened input of tasks.
22 ///
23 /// The `linearize` approach works in two parallelization phases:
24 /// * first phase to linearize the inputs in parallel over the non-linear data, and
25 /// * second phase to perform the computation in parallel over the linear data.
26 ///
27 /// See [`into_par_rec`] and [`into_par_rec_exact`] for examples.
28 ///
29 /// [`into_par_rec`]: crate::IntoParIterRec::into_par_rec
30 /// [`into_par_rec_exact`]: crate::IntoParIterRec::into_par_rec_exact
31 pub fn linearize(self) -> Par<ConIterVec<T>, R> {
32 let params = self.params();
33 let orchestrator = self.orchestrator().clone();
34 let items: Vec<_> = self.collect();
35 let iter = items.into_con_iter();
36 Par::new(orchestrator, params, iter)
37 }
38}
39
40impl<E, T, R, O, M1> ParMap<Rec<T, E>, O, M1, R>
41where
42 T: Send + Sync,
43 E: Fn(&T, &Queue<T>) + Sync,
44 R: ParallelRunner + Clone,
45 M1: Fn(T) -> O + Sync,
46{
47 /// Even with exact length, a recursive parallel iterator is much more dynamic than a flat parallel
48 /// iterator. This dynamic nature of shrinking and growing concurrently requires a greater parallelization
49 /// overhead. An alternative approach is to eagerly discover all tasks and then perform the parallel
50 /// computation over the flattened input of tasks.
51 ///
52 /// The `linearize` approach works in two parallelization phases:
53 /// * first phase to linearize the inputs in parallel over the non-linear data, and
54 /// * second phase to perform the computation in parallel over the linear data.
55 ///
56 /// See [`into_par_rec`] and [`into_par_rec_exact`] for examples.
57 ///
58 /// [`into_par_rec`]: crate::IntoParIterRec::into_par_rec
59 /// [`into_par_rec_exact`]: crate::IntoParIterRec::into_par_rec_exact
60 pub fn linearize(self) -> ParMap<ConIterVec<T>, O, M1, R> {
61 let (orchestrator, params, iter, map1) = self.destruct();
62 let par = Par::new(orchestrator.clone(), params, iter);
63 let items: Vec<_> = par.collect();
64 let iter = items.into_con_iter();
65 ParMap::new(orchestrator, params, iter, map1)
66 }
67}
68
69impl<E, T, R, Vo, X1> ParXap<Rec<T, E>, Vo, X1, R>
70where
71 T: Send + Sync,
72 E: Fn(&T, &Queue<T>) + Sync,
73 R: ParallelRunner + Clone,
74 X1: Fn(T) -> Vo + Sync,
75 Vo: TransformableValues<Fallibility = Infallible>,
76{
77 /// Even with exact length, a recursive parallel iterator is much more dynamic than a flat parallel
78 /// iterator. This dynamic nature of shrinking and growing concurrently requires a greater parallelization
79 /// overhead. An alternative approach is to eagerly discover all tasks and then perform the parallel
80 /// computation over the flattened input of tasks.
81 ///
82 /// The `linearize` approach works in two parallelization phases:
83 /// * first phase to linearize the inputs in parallel over the non-linear data, and
84 /// * second phase to perform the computation in parallel over the linear data.
85 ///
86 /// See [`into_par_rec`] and [`into_par_rec_exact`] for examples.
87 ///
88 /// [`into_par_rec`]: crate::IntoParIterRec::into_par_rec
89 /// [`into_par_rec_exact`]: crate::IntoParIterRec::into_par_rec_exact
90 pub fn linearize(self) -> ParXap<ConIterVec<T>, Vo, X1, R> {
91 let (orchestrator, params, iter, xap1) = self.destruct();
92 let par = Par::new(orchestrator.clone(), params, iter);
93 let items: Vec<_> = par.collect();
94 let iter = items.into_con_iter();
95 ParXap::new(orchestrator, params, iter, xap1)
96 }
97}