pub struct Reducer<G: Debug + Default, L: Debug + Default = G> { /* private fields */ }
Expand description
An OpenMP-style reducer that wraps a global value into a Mutex
,
providing shareable, cloneable copies with a local value;
the copies will be reduced into the global value when dropped.
The global value can be observed with peek
if the base
type is Clone
, whereas get
consumes self and returns
the global value.
For convenience, the global value and the local value have distinct type
parameters G
and L
, respectively; the second type defaults to the first
one.
Each shared copy has a reference to the Reducer
it was created from, so
you cannot call get
if there are still shared copies
around. For example, this code will not compile:
use openmp_reducer::Reducer;
let reducer = Reducer::<usize>::new(3, |global, local| *global += *local);
let mut shared = reducer.share();
// drop(shared); // uncommenting this line would make the code compile
assert_eq!(reducer.get(), 3);
§Examples
In this example, we manually spawn processes:
use openmp_reducer::Reducer;
use std::thread;
let mut reducer = Reducer::<usize>::new(5, |global, local| *global += *local);
std::thread::scope(|s| {
for i in 0..3 {
let mut shared = reducer.share();
s.spawn(move || {
*shared.as_mut() += 10;
});
}
});
// Initial value plus additional values from shared copies
assert_eq!(reducer.get(), 35);
You can obtain the same behavior with Rayon using
methods such as
for_each_with
and
map_with
:
use openmp_reducer::Reducer;
use rayon::prelude::*;
let mut reducer = Reducer::<usize>::new(5, |global, local| *global += *local);
(0..1000000).into_par_iter().
with_min_len(1000). // optional, might reduce the amount of cloning
for_each_with(reducer.share(), |shared, i| {
*shared.as_mut() += 1;
}
);
// Initial value plus additional values from clones
assert_eq!(reducer.get(), 1_000_005);
Note that you have to pass reducer.share()
, which can be cloned. Also,
since
for_each_with
might perform excessive cloning if jobs are too short, you can use
with_min_len
to reduce the amount of cloning.
Implementations§
Source§impl<G: Debug + Default, L: Debug + Default> Reducer<G, L>
impl<G: Debug + Default, L: Debug + Default> Reducer<G, L>
Sourcepub fn new(init: G, reduce: fn(global: &mut G, local: &L)) -> Self
pub fn new(init: G, reduce: fn(global: &mut G, local: &L)) -> Self
Creates a new reducer with a given reduction function.
The function must reduce the local value (second argument) into the global value (first argument). For the result to be deterministic, the global value must be the same regardless of the order in which the local values are reduced.
Returns a SharedReducer
referencing this Reducer
.
The SharedReducer
will be initialized with the default value of the
base type.
Sourcepub fn get(self) -> G
pub fn get(self) -> G
Consumes self and return the global value.
Note that you cannot call this method if there are still shared copies that have not been dropped.
If you just need to access the global value without consuming self, and
the base type is Clone
, use peek
.
§Panics
This method will panic if the mutex is poisoned.
peek
.