Skip to content

Commit

Permalink
Merge #970
Browse files Browse the repository at this point in the history
970: add fold_chunks and fold_chunks_with parallel iterators r=cuviper a=willcrozi

This adds two iterators to allow working with fixed-size chunks in a similar way to `chunks()` but without incurring the overhead of allocating a `Vec<T>` for each chunk.

Something similar was discussed in #773.

A call such as:
```
par_iter.fold_chunks(chunk_len, || init(), |acc, x| foo(acc, x))
```
would be functionally equivalent to:
```
par_iter.chunks(chunk_len)
    .map(|chunk|
        chunk.into_iter()
            .fold(init(), |acc, x| foo(acc, x|))
```
A final `fold()` (or `for_each()`, `sum()`, etc) across all mapped chunks can be chained by user code if needed, like this I think it's more flexible.

Co-authored-by: Will Crozier <[email protected]>
Co-authored-by: Josh Stone <[email protected]>
  • Loading branch information
3 people committed Nov 8, 2022
2 parents 690d0e0 + 66eb8ed commit 274499a
Show file tree
Hide file tree
Showing 7 changed files with 873 additions and 0 deletions.
31 changes: 31 additions & 0 deletions rayon-demo/src/factorial/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@ fn factorial_par_iter(b: &mut test::Bencher) {
b.iter(|| assert_eq!(fact(test::black_box(N)), f));
}

#[bench]
/// Compute the Factorial using rayon::fold_with.
fn factorial_fold_with(b: &mut test::Bencher) {
fn fact(n: u32) -> BigUint {
(1..n + 1)
.into_par_iter()
.with_min_len(64) // for fair comparison with factorial_fold_chunks_with()
.fold_with(BigUint::from(1_u32), |acc, x| acc.mul(x))
.reduce_with(Mul::mul)
.unwrap()
}

let f = factorial(N);
b.iter(|| assert_eq!(fact(test::black_box(N)), f));
}

#[bench]
/// Compute the Factorial using rayon::fold_chunks_with.
fn factorial_fold_chunks_with(b: &mut test::Bencher) {
fn fact(n: u32) -> BigUint {
(1..n + 1)
.into_par_iter()
.fold_chunks_with(64, BigUint::from(1_u32), |acc, x| acc.mul(x))
.reduce_with(Mul::mul)
.unwrap()
}

let f = factorial(N);
b.iter(|| assert_eq!(fact(test::black_box(N)), f));
}

#[bench]
/// Compute the Factorial using divide-and-conquer serial recursion.
fn factorial_recursion(b: &mut test::Bencher) {
Expand Down
2 changes: 2 additions & 0 deletions src/compile_fail/must_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ must_use! {
step_by /** v.par_iter().step_by(2); */
chain /** v.par_iter().chain(&v); */
chunks /** v.par_iter().chunks(2); */
fold_chunks /** v.par_iter().fold_chunks(2, || 0, |x, _| x); */
fold_chunks_with /** v.par_iter().fold_chunks_with(2, 0, |x, _| x); */
cloned /** v.par_iter().cloned(); */
copied /** v.par_iter().copied(); */
enumerate /** v.par_iter().enumerate(); */
Expand Down
Loading

0 comments on commit 274499a

Please sign in to comment.