From c705350dea4b208a02f4469323cd04e2ac82c974 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Thu, 19 Nov 2020 22:00:23 +0100 Subject: [PATCH] Implemented 'with_min_len' and 'with_max_len' operation --- asparit/src/core/iterator.rs | 81 ++++++++++++++- asparit/src/iter/mod.rs | 2 +- asparit/src/iter/{splits.rs => setup.rs} | 123 +++++++++++------------ 3 files changed, 138 insertions(+), 68 deletions(-) rename asparit/src/iter/{splits.rs => setup.rs} (61%) diff --git a/asparit/src/core/iterator.rs b/asparit/src/core/iterator.rs index 54ec56a..0205bb6 100644 --- a/asparit/src/core/iterator.rs +++ b/asparit/src/core/iterator.rs @@ -2,7 +2,8 @@ use std::cmp::{Ord, Ordering}; use std::iter::IntoIterator; use super::{ - Consumer, Executor, FromParallelIterator, IntoParallelIterator, Reducer, WithIndexedProducer, + Consumer, Executor, FromParallelIterator, IntoParallelIterator, Reducer, Setup, + WithIndexedProducer, }; use crate::{ @@ -35,8 +36,8 @@ use crate::{ product::Product, reduce::{Reduce, ReduceWith}, rev::Rev, + setup::SetupIter, skip::Skip, - splits::Splits, step_by::StepBy, sum::Sum, take::Take, @@ -1734,8 +1735,14 @@ pub trait ParallelIterator<'a>: Sized + Send { /// /// assert!(min >= 1234); /// ``` - fn with_splits(self, splits: usize) -> Splits { - Splits::new(self, splits) + fn with_splits(self, splits: usize) -> SetupIter { + SetupIter::new( + self, + Setup { + splits: Some(splits), + ..Default::default() + }, + ) } } @@ -2225,4 +2232,70 @@ pub trait IndexedParallelIterator<'a>: ParallelIterator<'a> { fn rev(self) -> Rev { Rev::new(self) } + + /// Sets the minimum length of iterators desired to process in each + /// thread. Rayon will not split any smaller than this length, but + /// of course an iterator could already be smaller to begin with. + /// + /// Producers like `zip` and `interleave` will use greater of the two + /// minimums. + /// Chained iterators and iterators inside `flat_map` may each use + /// their own minimum length. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// + /// let min = (0..1_000_000) + /// .into_par_iter() + /// .with_min_len(1234) + /// .fold(|| 0, |acc, _| acc + 1) // count how many are in this segment + /// .min().unwrap(); + /// + /// assert!(min >= 1234); + /// ``` + fn with_min_len(self, min: usize) -> SetupIter { + SetupIter::new( + self, + Setup { + min_len: Some(min), + ..Default::default() + }, + ) + } + + /// Sets the maximum length of iterators desired to process in each + /// thread. Rayon will try to split at least below this length, + /// unless that would put it below the length from `with_min_len()`. + /// For example, given min=10 and max=15, a length of 16 will not be + /// split any further. + /// + /// Producers like `zip` and `interleave` will use lesser of the two + /// maximums. + /// Chained iterators and iterators inside `flat_map` may each use + /// their own maximum length. + /// + /// # Examples + /// + /// ``` + /// use rayon::prelude::*; + /// + /// let max = (0..1_000_000) + /// .into_par_iter() + /// .with_max_len(1234) + /// .fold(|| 0, |acc, _| acc + 1) // count how many are in this segment + /// .max().unwrap(); + /// + /// assert!(max <= 1234); + /// ``` + fn with_max_len(self, max: usize) -> SetupIter { + SetupIter::new( + self, + Setup { + max_len: Some(max), + ..Default::default() + }, + ) + } } diff --git a/asparit/src/iter/mod.rs b/asparit/src/iter/mod.rs index 8389ac5..220b69f 100644 --- a/asparit/src/iter/mod.rs +++ b/asparit/src/iter/mod.rs @@ -27,8 +27,8 @@ pub mod position; pub mod product; pub mod reduce; pub mod rev; +pub mod setup; pub mod skip; -pub mod splits; pub mod step_by; pub mod sum; pub mod take; diff --git a/asparit/src/iter/splits.rs b/asparit/src/iter/setup.rs similarity index 61% rename from asparit/src/iter/splits.rs rename to asparit/src/iter/setup.rs index 426c229..23c9aa1 100644 --- a/asparit/src/iter/splits.rs +++ b/asparit/src/iter/setup.rs @@ -4,18 +4,18 @@ use crate::{ WithProducer, WithSetup, }; -pub struct Splits { +pub struct SetupIter { base: X, - splits: usize, + setup: Setup, } -impl Splits { - pub fn new(base: X, splits: usize) -> Self { - Self { base, splits } +impl SetupIter { + pub fn new(base: X, setup: Setup) -> Self { + Self { base, setup } } } -impl<'a, X> ParallelIterator<'a> for Splits +impl<'a, X> ParallelIterator<'a> for SetupIter where X: ParallelIterator<'a>, { @@ -28,8 +28,8 @@ where D: Send + 'a, R: Reducer + Send + 'a, { - let splits = self.splits; - let consumer = SplitsConsumer { base, splits }; + let setup = self.setup; + let consumer = SetupIterConsumer { base, setup }; self.base.drive(executor, consumer) } @@ -39,7 +39,7 @@ where } } -impl<'a, X> IndexedParallelIterator<'a> for Splits +impl<'a, X> IndexedParallelIterator<'a> for SetupIter where X: IndexedParallelIterator<'a>, { @@ -50,8 +50,8 @@ where D: Send + 'a, R: Reducer + Send + 'a, { - let splits = self.splits; - let consumer = SplitsConsumer { base, splits }; + let setup = self.setup; + let consumer = SetupIterConsumer { base, setup }; self.base.drive_indexed(executor, consumer) } @@ -61,7 +61,7 @@ where } } -impl<'a, X> WithProducer<'a> for Splits +impl<'a, X> WithProducer<'a> for SetupIter where X: WithProducer<'a>, { @@ -71,13 +71,13 @@ where where CB: ProducerCallback<'a, Self::Item>, { - let splits = self.splits; + let setup = self.setup; - self.base.with_producer(SplitsCallback { base, splits }) + self.base.with_producer(SetupIterCallback { base, setup }) } } -impl<'a, X> WithIndexedProducer<'a> for Splits +impl<'a, X> WithIndexedProducer<'a> for SetupIter where X: WithIndexedProducer<'a>, { @@ -87,21 +87,21 @@ where where CB: IndexedProducerCallback<'a, Self::Item>, { - let splits = self.splits; + let setup = self.setup; self.base - .with_indexed_producer(SplitsCallback { base, splits }) + .with_indexed_producer(SetupIterCallback { base, setup }) } } -/* SplitsCallback */ +/* SetupIterCallback */ -struct SplitsCallback { +struct SetupIterCallback { base: CB, - splits: usize, + setup: Setup, } -impl<'a, CB, I> ProducerCallback<'a, I> for SplitsCallback +impl<'a, CB, I> ProducerCallback<'a, I> for SetupIterCallback where CB: ProducerCallback<'a, I>, { @@ -111,13 +111,13 @@ where where P: Producer + 'a, { - let splits = self.splits; + let setup = self.setup; - self.base.callback(SplitsProducer { base, splits }) + self.base.callback(SetupIterProducer { base, setup }) } } -impl<'a, CB, I> IndexedProducerCallback<'a, I> for SplitsCallback +impl<'a, CB, I> IndexedProducerCallback<'a, I> for SetupIterCallback where CB: IndexedProducerCallback<'a, I>, { @@ -127,32 +127,29 @@ where where P: IndexedProducer + 'a, { - let splits = self.splits; + let setup = self.setup; - self.base.callback(SplitsProducer { base, splits }) + self.base.callback(SetupIterProducer { base, setup }) } } -/* SplitsProducer */ +/* SetupIterProducer */ -struct SplitsProducer

{ +struct SetupIterProducer

{ base: P, - splits: usize, + setup: Setup, } -impl

WithSetup for SplitsProducer

+impl

WithSetup for SetupIterProducer

where P: WithSetup, { fn setup(&self) -> Setup { - self.base.setup().merge(Setup { - splits: Some(self.splits), - ..Default::default() - }) + self.base.setup().merge(self.setup.clone()) } } -impl

Producer for SplitsProducer

+impl

Producer for SetupIterProducer

where P: Producer, { @@ -164,11 +161,14 @@ where } fn split(self) -> (Self, Option) { - let splits = self.splits; + let setup = self.setup; let (left, right) = self.base.split(); - let left = Self { base: left, splits }; - let right = right.map(|base| Self { base, splits }); + let left = Self { + base: left, + setup: setup.clone(), + }; + let right = right.map(|base| Self { base, setup }); (left, right) } @@ -181,7 +181,7 @@ where } } -impl

IndexedProducer for SplitsProducer

+impl

IndexedProducer for SetupIterProducer

where P: IndexedProducer, { @@ -197,14 +197,14 @@ where } fn split_at(self, index: usize) -> (Self, Self) { - let splits = self.splits; + let setup = self.setup; let (left, right) = self.base.split_at(index); - let left = Self { base: left, splits }; - let right = Self { - base: right, - splits, + let left = Self { + base: left, + setup: setup.clone(), }; + let right = Self { base: right, setup }; (left, right) } @@ -217,26 +217,23 @@ where } } -/* SplitsConsumer */ +/* SetupIterConsumer */ -struct SplitsConsumer { +struct SetupIterConsumer { base: C, - splits: usize, + setup: Setup, } -impl WithSetup for SplitsConsumer +impl WithSetup for SetupIterConsumer where C: WithSetup, { fn setup(&self) -> Setup { - self.base.setup().merge(Setup { - splits: Some(self.splits), - ..Default::default() - }) + self.base.setup().merge(self.setup.clone()) } } -impl Consumer for SplitsConsumer +impl Consumer for SetupIterConsumer where C: Consumer, { @@ -245,27 +242,27 @@ where type Result = C::Result; fn split(self) -> (Self, Self, Self::Reducer) { - let splits = self.splits; + let setup = self.setup; let (left, right, reducer) = self.base.split(); - let left = Self { base: left, splits }; - let right = Self { - base: right, - splits, + let left = Self { + base: left, + setup: setup.clone(), }; + let right = Self { base: right, setup }; (left, right, reducer) } fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { - let splits = self.splits; + let setup = self.setup; let (left, right, reducer) = self.base.split_at(index); - let left = Self { base: left, splits }; - let right = Self { - base: right, - splits, + let left = Self { + base: left, + setup: setup.clone(), }; + let right = Self { base: right, setup }; (left, right, reducer) }