@@ -21,11 +21,14 @@ use crate::split_at::SplitPreference;
2121#[ derive( Copy , Clone , Debug ) ]
2222pub struct Parallel < I > {
2323 iter : I ,
24+ min_len : usize ,
2425}
2526
27+ const DEFAULT_MIN_LEN : usize = 1 ;
28+
2629/// Parallel producer wrapper.
2730#[ derive( Copy , Clone , Debug ) ]
28- struct ParallelProducer < I > ( I ) ;
31+ struct ParallelProducer < I > ( I , usize ) ;
2932
3033macro_rules! par_iter_wrapper {
3134 // thread_bounds are either Sync or Send + Sync
@@ -40,6 +43,7 @@ macro_rules! par_iter_wrapper {
4043 fn into_par_iter( self ) -> Self :: Iter {
4144 Parallel {
4245 iter: self ,
46+ min_len: DEFAULT_MIN_LEN ,
4347 }
4448 }
4549 }
@@ -67,7 +71,7 @@ macro_rules! par_iter_wrapper {
6771 fn with_producer<Cb >( self , callback: Cb ) -> Cb :: Output
6872 where Cb : ProducerCallback <Self :: Item >
6973 {
70- callback. callback( ParallelProducer ( self . iter) )
74+ callback. callback( ParallelProducer ( self . iter, self . min_len ) )
7175 }
7276
7377 fn len( & self ) -> usize {
@@ -106,7 +110,7 @@ macro_rules! par_iter_wrapper {
106110
107111 fn split_at( self , i: usize ) -> ( Self , Self ) {
108112 let ( a, b) = self . 0 . split_at( i) ;
109- ( ParallelProducer ( a) , ParallelProducer ( b) )
113+ ( ParallelProducer ( a, self . 1 ) , ParallelProducer ( b, self . 1 ) )
110114 }
111115 }
112116
@@ -131,11 +135,11 @@ macro_rules! par_iter_view_wrapper {
131135 fn into_par_iter( self ) -> Self :: Iter {
132136 Parallel {
133137 iter: self ,
138+ min_len: DEFAULT_MIN_LEN ,
134139 }
135140 }
136141 }
137142
138-
139143 impl <' a, A , D > ParallelIterator for Parallel <$view_name<' a, A , D >>
140144 where D : Dimension ,
141145 A : $( $thread_bounds) * ,
@@ -144,28 +148,47 @@ macro_rules! par_iter_view_wrapper {
144148 fn drive_unindexed<C >( self , consumer: C ) -> C :: Result
145149 where C : UnindexedConsumer <Self :: Item >
146150 {
147- bridge_unindexed( ParallelProducer ( self . iter) , consumer)
151+ bridge_unindexed( ParallelProducer ( self . iter, self . min_len ) , consumer)
148152 }
149153
150154 fn opt_len( & self ) -> Option <usize > {
151155 None
152156 }
153157 }
154158
159+ impl <' a, A , D > Parallel <$view_name<' a, A , D >>
160+ where D : Dimension ,
161+ A : $( $thread_bounds) * ,
162+ {
163+ /// Sets the minimum number of elements desired to process in each job. This will not be
164+ /// split any smaller than this length, but of course a producer could already be smaller
165+ /// to begin with.
166+ ///
167+ /// ***Panics*** if `min_len` is zero.
168+ pub fn with_min_len( self , min_len: usize ) -> Self {
169+ assert_ne!( min_len, 0 , "Minimum number of elements must at least be one to avoid splitting off empty tasks." ) ;
170+
171+ Self {
172+ min_len,
173+ ..self
174+ }
175+ }
176+ }
177+
155178 impl <' a, A , D > UnindexedProducer for ParallelProducer <$view_name<' a, A , D >>
156179 where D : Dimension ,
157180 A : $( $thread_bounds) * ,
158181 {
159182 type Item = <$view_name<' a, A , D > as IntoIterator >:: Item ;
160183 fn split( self ) -> ( Self , Option <Self >) {
161- if self . 0 . len( ) <= 1 {
184+ if self . 0 . len( ) <= self . 1 {
162185 return ( self , None )
163186 }
164187 let array = self . 0 ;
165188 let max_axis = array. max_stride_axis( ) ;
166189 let mid = array. len_of( max_axis) / 2 ;
167190 let ( a, b) = array. split_at( max_axis, mid) ;
168- ( ParallelProducer ( a) , Some ( ParallelProducer ( b) ) )
191+ ( ParallelProducer ( a, self . 1 ) , Some ( ParallelProducer ( b, self . 1 ) ) )
169192 }
170193
171194 fn fold_with<F >( self , folder: F ) -> F
@@ -217,6 +240,7 @@ macro_rules! zip_impl {
217240 fn into_par_iter( self ) -> Self :: Iter {
218241 Parallel {
219242 iter: self ,
243+ min_len: DEFAULT_MIN_LEN ,
220244 }
221245 }
222246 }
@@ -233,7 +257,7 @@ macro_rules! zip_impl {
233257 fn drive_unindexed<Cons >( self , consumer: Cons ) -> Cons :: Result
234258 where Cons : UnindexedConsumer <Self :: Item >
235259 {
236- bridge_unindexed( ParallelProducer ( self . iter) , consumer)
260+ bridge_unindexed( ParallelProducer ( self . iter, self . min_len ) , consumer)
237261 }
238262
239263 fn opt_len( & self ) -> Option <usize > {
@@ -251,11 +275,11 @@ macro_rules! zip_impl {
251275 type Item = ( $( $p:: Item , ) * ) ;
252276
253277 fn split( self ) -> ( Self , Option <Self >) {
254- if ! self . 0 . can_split ( ) {
278+ if self . 0 . size ( ) <= self . 1 {
255279 return ( self , None )
256280 }
257281 let ( a, b) = self . 0 . split( ) ;
258- ( ParallelProducer ( a) , Some ( ParallelProducer ( b) ) )
282+ ( ParallelProducer ( a, self . 1 ) , Some ( ParallelProducer ( b, self . 1 ) ) )
259283 }
260284
261285 fn fold_with<Fold >( self , folder: Fold ) -> Fold
@@ -284,6 +308,25 @@ zip_impl! {
284308 [ P1 P2 P3 P4 P5 P6 ] ,
285309}
286310
311+ impl < D , Parts > Parallel < Zip < Parts , D > >
312+ where
313+ D : Dimension ,
314+ {
315+ /// Sets the minimum number of elements desired to process in each job. This will not be
316+ /// split any smaller than this length, but of course a producer could already be smaller
317+ /// to begin with.
318+ ///
319+ /// ***Panics*** if `min_len` is zero.
320+ pub fn with_min_len ( self , min_len : usize ) -> Self {
321+ assert_ne ! ( min_len, 0 , "Minimum number of elements must at least be one to avoid splitting off empty tasks." ) ;
322+
323+ Self {
324+ min_len,
325+ ..self
326+ }
327+ }
328+ }
329+
287330/// A parallel iterator (unindexed) that produces the splits of the array
288331/// or producer `P`.
289332pub ( crate ) struct ParallelSplits < P > {
0 commit comments