Reputation: 28753
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:
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.
Upvotes: 1
Views: 1271
Reputation: 70870
Any iterator can be converted into a parallel iterator by calling par_bridge()
. However, you may be able to implement ParallelIterator
more efficiently.
Upvotes: 2