并行处理 vec:如何安全或不使用不稳定的功能?
Processing vec in parallel: how to do safely, or without using unstable features?
我有一个巨大的矢量,我希望能够 load/act 并行处理,例如在一个线程中加载前十万个索引,然后在另一个线程中加载,依此类推。由于这将是代码中非常热门的部分,因此我提出了以下概念验证不安全代码来在没有 Arcs 和 Mutexes 的情况下执行此操作:
let mut data:Vec<u32> = vec![1u32, 2, 3];
let head = data.as_mut_ptr();
let mut guards = (0..3).map(|i|
unsafe {
let mut target = std::ptr::Unique::new(head.offset(i));
let guard = spawn(move || {
std::ptr::write(target.get_mut(), 10 + i as u32);
});
guard
});
这里有什么我遗漏的可能导致爆炸的事情吗?
这使用了 #![feature(unique)]
所以我不知道如何在稳定版中使用它。有没有办法在稳定的情况下做这种事情(理想情况下安全地不使用 Arc
和 Mutex
的原始指针和开销)?
此外,查看 documentation for Unique
,上面写着
It also implies that the referent of the pointer should not be modified without a unique path to the Unique
reference
我不清楚"unique path"是什么意思。
可以为此使用外部库,例如simple_parallel
(免责声明,我写的)允许一个人写:
extern crate simple_parallel;
let mut data = vec![1u32, 2, 3, 4, 5];
let mut pool = simple_parallel::Pool::new(4);
pool.for_(data.chunks_mut(3), |target| {
// do stuff with `target`
})
chunks
and chunks_mut
方法是将 T
中的 vector/slice 分割成大小相等的块的完美方法:它们分别 return 一个遍历类型 [ 的元素的迭代器=15=] 和 &mut [T]
.
如今,rayon
板条箱是这类事情的实际标准:
use rayon::prelude::*;
fn main() {
let mut data = vec![1, 2, 3];
data.par_iter_mut()
.enumerate()
.for_each(|(i, x)| *x = 10 + i as u32);
assert_eq!(vec![10, 11, 12], data);
}
请注意,这与使用标准迭代器的 single-threaded 版本只有一行不同,后者会将 par_iter_mut
替换为 iter_mut
。
我有一个巨大的矢量,我希望能够 load/act 并行处理,例如在一个线程中加载前十万个索引,然后在另一个线程中加载,依此类推。由于这将是代码中非常热门的部分,因此我提出了以下概念验证不安全代码来在没有 Arcs 和 Mutexes 的情况下执行此操作:
let mut data:Vec<u32> = vec![1u32, 2, 3];
let head = data.as_mut_ptr();
let mut guards = (0..3).map(|i|
unsafe {
let mut target = std::ptr::Unique::new(head.offset(i));
let guard = spawn(move || {
std::ptr::write(target.get_mut(), 10 + i as u32);
});
guard
});
这里有什么我遗漏的可能导致爆炸的事情吗?
这使用了 #![feature(unique)]
所以我不知道如何在稳定版中使用它。有没有办法在稳定的情况下做这种事情(理想情况下安全地不使用 Arc
和 Mutex
的原始指针和开销)?
此外,查看 documentation for Unique
,上面写着
It also implies that the referent of the pointer should not be modified without a unique path to the
Unique
reference
我不清楚"unique path"是什么意思。
可以为此使用外部库,例如simple_parallel
(免责声明,我写的)允许一个人写:
extern crate simple_parallel;
let mut data = vec![1u32, 2, 3, 4, 5];
let mut pool = simple_parallel::Pool::new(4);
pool.for_(data.chunks_mut(3), |target| {
// do stuff with `target`
})
chunks
and chunks_mut
方法是将 T
中的 vector/slice 分割成大小相等的块的完美方法:它们分别 return 一个遍历类型 [ 的元素的迭代器=15=] 和 &mut [T]
.
如今,rayon
板条箱是这类事情的实际标准:
use rayon::prelude::*;
fn main() {
let mut data = vec![1, 2, 3];
data.par_iter_mut()
.enumerate()
.for_each(|(i, x)| *x = 10 + i as u32);
assert_eq!(vec![10, 11, 12], data);
}
请注意,这与使用标准迭代器的 single-threaded 版本只有一行不同,后者会将 par_iter_mut
替换为 iter_mut
。