能否使用rayon并行实现Vec.retain()方法?
使用Rayon并行实现Vec.retain()的方法
直接用par_iter_mut().retain()不行,原因有两个:
- Rayon的并行可变迭代器没有提供
retain方法; retain的核心是原地调整元素位置、修改Vec长度,这个过程依赖顺序化的内存操作,并行直接操作会引发数据竞争和索引混乱,根本无法安全执行。
下面提供两种可行的并行实现方案:
方案1:原地修改(接近原生retain的行为)
先通过并行迭代标记需要保留的元素,再用串行的retain完成原地整理:
use rayon::prelude::*; fn main() { let mut vec = vec![1, 2, 3, 4, 5, 6]; // 并行生成元素保留标记 let keep: Vec<bool> = vec.par_iter().map(|&x| x % 2 == 0).collect(); // 串行根据标记保留元素 let mut idx = 0; vec.retain(|_| { let flag = keep[idx]; idx += 1; flag }); assert_eq!(vec, vec![2, 4, 6]); }
这种方式既利用并行加速了元素的判断逻辑,又保证了原地修改的安全性,适合需要复用原有Vec内存的场景。
方案2:生成新Vec(更简洁)
如果不需要原地修改,直接用into_par_iter配合filter并行过滤后生成新Vec:
use rayon::prelude::*; fn main() { let vec = vec![1, 2, 3, 4, 5, 6]; // 并行过滤生成新Vec let filtered_vec: Vec<i32> = vec.into_par_iter().filter(|&x| x % 2 == 0).collect(); assert_eq!(filtered_vec, vec![2, 4, 6]); }
这个写法更简单,不需要额外的标记数组,但会分配新的内存空间。
内容的提问来源于stack exchange,提问作者Moold
相关产品推荐
相关产品推荐

