Expand description
Parallel pipelined map over iterators.
This crate adds the plmap and scoped_plmap functions to iterators allowing easy pipelined parallelism. Because the implementation uses pipelining, it preserves order, but also suffers from head of line blocking.
Examples
Parallel pipelined mapping:
// Import the iterator extension trait.
use plmap::PipelineMap;
// Map over an iterator in parallel with 5 worker threads.
fn example() {
for i in (0..100).plmap(5, |x| x * 2) {
println!("i={}", i);
}
}
Scoped and parallel pipelined mapping:
use plmap::ScopedPipelineMap;
fn example() {
crossbeam_utils::thread::scope(|s| {
// Using a thread scope let's you use non 'static lifetimes.
for (i, v) in (0..100).scoped_plmap(s, 5, |x| x * 2).enumerate() {
println!("i={}", i);
}
}).unwrap()
}
Map with your own type instead of a function:
use plmap::{Mapper, PipelineMap};
// The type must support clone as each worker thread gets a copy.
#[derive(Clone)]
struct CustomMapper {}
impl Mapper<i32> for CustomMapper {
type Out = i64;
fn apply(&mut self, x: i32) -> i64 {
(x * 2) as i64
}
}
fn custom_mapper() {
for i in (0..100).plmap(5, CustomMapper{}) {
println!("i={}", i);
}
}
Structs
Pipeline is a wrapper around a worker pool and implements
iterator. Usually they should be created via the PipelineMap
extension trait and calling plmap on an iterator.
ScopedPipeline is a wrapper around a worker pool and implements
iterator. Usually they should be created via the PipelineMap
extension trait and calling plmap on an iterator.
Traits
Mapper is a type that can map values from In to Out,
You can implement this trait to plmap on types other than closures.
PipelineMap can be imported to add the plmap function to iterators.
ScopedPipelineMap can be imported to add the scoped_plmap function to iterators.