Rayon
library already implemented the partition
function, and it only divides a vector into two parts, but I need three parts. I code this:
use rayon::prelude::*;
trait IterExt<T> {
fn for_each(self, f: impl Fn(T) + Sync + Send);
fn partition3(self, predicate1: impl FnMut(&T) -> bool + Sync + Send, predicate2: impl FnMut(&T) -> bool + Sync + Send) -> (Vec<T>, Vec<T>, Vec<T>) where T: Sync;
}
impl<T> IterExt<T> for Vec<T> where T: Send {
fn for_each(self, f: impl Fn(T) + Sync + Send) {
self.into_par_iter().for_each(f);
}
fn partition3(self, mut predicate1: impl FnMut(&T) -> bool + Sync + Send, mut predicate2: impl FnMut(&T) -> bool + Sync + Send) -> (Vec<T>, Vec<T>, Vec<T>) where T: Sync {
let mut first = vec![];
let mut second = vec![];
let mut third = vec![];
self.for_each(|e|
if predicate1(&e) { first.push(e) }
else if predicate2(&e) { second.push(e) }
else { third.push(e) }
);
(first, second, third)
}
}
I tried to write for a long time, but still got stuck in borrow checker.
I want to know how to write a correct parallel function to divide a vector into three parts.
1
共 1 条评论, 1 页
评论区
写评论I don't think you can declare
predicate1
andpredicate2
asFnMut
. When rayon executes the partition parallelly, different threads may need to callpredicate1
at the same time, which violates the borrow rule since it requires a mutable reference topredicate1
to call throughFnMut
.What you should do is to make predicates
Fn
, and use interior mutability and proper synchronization if mutation is needed.PS: use
partition_map
to partition into multiple collections.