并行处理vec:如何安全地进行,或者不使用不稳定的功能?

sgl*_*div 9 parallel-processing unsafe rust

我有一个巨大的向量,我希望能够并行加载/操作,例如,在一个线程中加载前十万个索引,在另一个线程中加载下一个,依此类推.由于这将成为代码中非常热门的一部分,我已经提出了以下概念验证不安全代码,以便在没有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
  });
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么可以使这可能爆炸吗?

这使用#![feature(unique)]所以我不知道如何在稳定中使用它.有没有办法在稳定中做这种事情(理想情况下安全,不使用原始指针和开销的Arc's和Mutex's)?

另外,看一下 文档Unique,它说

它还意味着如果没有引用的唯一路径,则不应修改指针的Unique引用

我不清楚"独特路径"是什么意思.

Jac*_*nor 18

今天,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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这与使用标准迭代器的单线程版本仅有一行不同,后者将替换par_iter_mutiter_mut

另请参见在Rust和Zig中编写一个小型射线跟踪器


huo*_*uon 8

可以使用外部库,例如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`
})
Run Code Online (Sandbox Code Playgroud)

chunkschunks_mut方法是对的矢量/切片分割的最佳方式Ts转换相等大小的块:它们分别比类型的元素返回一个迭代&[T]&mut [T].

  • 我用 https://github.com/rust-lang/threadpool 推出了我自己的。http://huonw.github.io/blog/2015/05/finding-closure-in-rust/ 非常有帮助。 (2认同)