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