multithreadingrustrayon

Using par_iter and Rayon in Rust


Suppose I want to parallelise the code below which takes two Rust vectors and sums each element, returning a new vector in the same order as the originals:

a = b.iter().zip(c.iter()).map(|(aa, bb)|{aa + bb}).collect();

Using something like this:

a = b.par_iter().zip(c.par_iter()).map(|(aa, bb)|{aa + bb}).collect();
  1. Do I need to use par_iter for the zip input as well (as shown)?
  2. Can I be sure that the collected output vector will have the summed values in the same order as the input and will not be altered by threads ending at different times?

Solution

  • The answers to your questions are yes and yes. However, there's many details that are involved.

    If you find calling c.par_iter() to be tedious, you can instead write b.par_iter().zip(&c), which will call c.par_iter() for you. This also applies to plain iterators and .iter().

    Rayon also has a convenient shorthand for creating many zipped parallel iterators, which is especially useful if you need to zip more than two:

    (&b, &c).into_par_iter().map(|(bb, cc)| bb + cc).collect()
    

    And if you look at the docs for collect, you will find mention of collect_into_vec, which will work more efficiently than collect.

    let mut a = Vec::new();
    (&b, &c).into_par_iter().map(|(bb, cc)| bb + cc).collect_into_vec(&mut a);