Search code examples
parallel-processingrustrayon

How do I detect overflow on a sum of integers using Rayon?


Is there a way to detect an overflow in Rayon and force it to panic instead of having an infinite loop?

extern crate rayon;

use rayon::prelude::*;

fn main() {
    let sample: Vec<u32> = (0..50000000).collect();
    let sum: u32 = sample.par_iter().sum();

    println!("{}",sum );
}

Playground


Solution

  • You are looking for ParallelIterator::try_reduce. The documentation example does what you are looking for (and more):

    use rayon::prelude::*;
    
    // Compute the sum of squares, being careful about overflow.
    fn sum_squares<I: IntoParallelIterator<Item = i32>>(iter: I) -> Option<i32> {
        iter.into_par_iter()
            .map(|i| i.checked_mul(i))            // square each item,
            .try_reduce(|| 0, i32::checked_add)   // and add them up!
    }
    assert_eq!(sum_squares(0..5), Some(0 + 1 + 4 + 9 + 16));
    
    // The sum might overflow
    assert_eq!(sum_squares(0..10_000), None);
    
    // Or the squares might overflow before it even reaches `try_reduce`
    assert_eq!(sum_squares(1_000_000..1_000_001), None);
    

    Specifically for your example:

    extern crate rayon;
    
    use rayon::prelude::*;
    
    fn main() {
        let sample: Vec<u32> = (0..50000000).collect();
        let sum = sample
            .into_par_iter()
            .map(Some)
            .try_reduce(
                || 0, 
                |a, b| a.checked_add(b)
            );
    
        println!("{:?}", sum);
    }
    

    The collect is unneeded inefficiency, but I've left it for now.