使用索引数组并行写入数组

Parallel write to array with an indices array

我无法理解来自 C++ 的 Rust 中的并发模型。

我的数组将使用定义索引的另一个数组同时访问。例如(伪代码):

let indices = [1, 2, 3, 4, 1, 2, 3, 2, 1, 1, 3, 2, 2];
let mut arr = [1, 2, 3, 4, 5, 6, 7, 8, 10];

indices.iter_par().for_each(|x| {
    arr[x] += x;
});

在 C++ 中,我会使用锁或原子访问来保护 arr 中的每个索引。我怎么能在 Rust 中做同样的事情?

编辑

我还有一个相关问题。

我如何才能将普通数组作为可变数组传递给并行迭代器,我确定不会出现竞争条件?

let indices = [1, 2, 3, 4, 5, 6, 7, 8];
let mut arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

indices.iter_par().for_each(|x| {
    arr[x] = some_function(x);
});

如果您需要为每个项目锁定,我不知道并行执行此操作的意义是什么,但您可以使用数组周围的 Mutex 进行变异来实现此目的:

use rayon::prelude::*;
use std::sync::Mutex;

fn main() {
    let indices = [1, 2, 3, 4, 1, 2, 3, 2, 1, 1, 3, 2, 2];
    let arr = Mutex::new([1, 2, 3, 4, 5, 6, 7, 8, 10]);

    indices.par_iter().for_each(|&x| {
        let mut arr = arr.lock().unwrap();
        arr[x] += x;
    });
}

playground

编辑

根据评论,您可以让每个元素都是原子的:

use rayon::prelude::*;
use std::sync::atomic::{AtomicUsize, Ordering};

fn main() {
    let indices = [1, 2, 3, 4, 1, 2, 3, 2, 1, 1, 3, 2, 2];
    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
        .iter()
        .map(|&n| AtomicUsize::new(n))
        .collect::<Vec<_>>();

    indices.par_iter().for_each(|&x| {
        arr[x].fetch_add(x, Ordering::SeqCst);
    });
}