Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Rayon support for itertools tuple_combinations

I’m trying to use Rayon‘s par_iter over a TupleCombinations struct from itertools as in the code below.

use itertools::Itertools;
use rayon::prelude::*;

fn main() {
    let v: Vec<i32> = vec!(1, 2, 3);
    let t = v.iter().tuple_combinations::<(_, _)>();
    let sum: i32 = t.par_iter().map(|&(i, j)| i * j).sum();
    println!("{}", sum);
}

The problem is that Rayon seems to expect something which implements the IntoIterator trait, but tuple_combinations returns a TupleCombinations struct which implements Iterator. I end up with the error below. I believe the solution is to implement IntoParallelIterator for TupleCombinations but it seems like this isn’t possible to do since there are some private trait bounds that must be satisfied. I thought I would see if anyone

error[E0599]: the method `par_iter` exists for struct `TupleCombinations<std::slice::Iter<'_, i32>, (&i32, &i32)>`, but its trait bounds were not satisfied
   --> src/main.rs:8:22
    |
8   |     let sum: i32 = t.par_iter().map(|&(i, j)| i * j).sum();
    |                      ^^^^^^^^ method cannot be called on `TupleCombinations<std::slice::Iter<'_, i32>, (&i32, &i32)>` due to unsatisfied trait bounds
    |
   ::: /home/mmior/.cargo/registry/src/github.com-1ecc6299db9ec823/itertools-0.10.3/src/adaptors/mod.rs:701:1
    |
701 | pub struct TupleCombinations<I, T>
    | ---------------------------------- doesn't satisfy `_: rayon::iter::IntoParallelRefIterator`
    |
    = note: the following trait bounds were not satisfied:
            `&TupleCombinations<std::slice::Iter<'_, i32>, (&i32, &i32)>: IntoParallelIterator`
            which is required by `TupleCombinations<std::slice::Iter<'_, i32>, (&i32, &i32)>: rayon::iter::IntoParallelRefIterator`

I started trying to implement this using a wrapper struct as follows:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

use itertools::{Itertools, TupleCombinations};
use rayon::prelude::*;

struct MyPairGenerator {
    values: Vec<i32>,
}

//TupleCombinations<std::slice::Iter<'_, i32>, (&i32, &i32)>
impl IntoIterator for MyPairGenerator {
    type Item = (i32, i32);
    type IntoIter = TupleCombinations<std::vec::IntoIter<i32>, (i32, i32)>;

    fn into_iter(self) -> Self::IntoIter {
        self.values.into_iter().tuple_combinations::<(i32, i32)>()
    }
}

fn main() {
    let v: Vec<i32> = vec!(1, 2, 3);
    let t = MyPairGenerator { values: v };
    let sum = t.par_iter().map(|&(i, j)| i * j).sum();
    println!("{}", sum);
}

It seems like now I should be able to implement IntoParallelIterator for MyPairGenerator, but I’m stuck as to where to start. Rayon seems to use private macros to do a lot of the work.

>Solution :

Any iterator can be converted into a parallel iterator by calling par_bridge(). However, you may be able to implement ParallelIterator more efficiently.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading