假设我们希望将向量的每个切片中的每个元素加倍(原地),其中切片由一对(开始,结束)位置的列表定义.下面的代码以习惯用法表达了intent,但由于parallel for_each
内部的vector的可变borrow 而无法编译:
use rayon::prelude::*;
fn main() {
let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let slice_pairs = vec![(0, 3), (4, 7), (8, 10)];
slice_pairs.into_par_iter().for_each(|(start, end)| {
let slice = &mut data[start..end];
for elem in slice.iter_mut() {
*elem *= 2;
}
});
println!("{:?}", data);
}
这里有一个真正的潜在数据竞争—为了排除它们,您需要判断切片是否重叠.问题是在Rust中最好的方式是什么,通过不安全的代码或安全的API.下面的代码使用unsafe
来"继续做这个";我的问题是是否有比下面更好的方法(它将向量的基指针转换为i64,并返回到"盲目"借位判断器的问题).
use rayon::prelude::*;
use std::mem;
fn main() {
let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let slice_pairs = vec![(0, 4), (4, 7), (7, 10)];
let ptr_outer = data.as_mut_ptr();
let ptr_int : i64 = unsafe { mem::transmute(ptr_outer) };
slice_pairs.into_par_iter().for_each(|(start, end)| {
unsafe {
let ptr : *mut i32 = mem::transmute(ptr_int);
let slice = std::slice::from_raw_parts_mut(ptr.add(start), end - start);
for elem in slice.iter_mut() {
*elem *= 2;
}
}
});
println!("{:?}", data);
}