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}