2

This question is analogical to Parallel write to array with an indices array except that I guarantee the indices to be unique.

let indices = [1, 4, 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);
});

Is there a way to achieve this in Rayon? Perhaps I should somehow use unsafe, because obviously borrow checker can't verify uniqueness of indices.

alagris
  • 1,838
  • 16
  • 31
  • Sharing a mutable container seems to be a (soft) anti-pattern with rayon. Something like [fold/reduce into hasmap](https://stackoverflow.com/a/57643239/235548) can be an alternative, depending on the actual task. – maxy Jan 25 '22 at 12:58

1 Answers1

1

You can certainly do it with unsafe, for example by sending a pointer to the threads:

// thin wrapper over pointer to make it Send/Sync
#[derive(Copy, Clone)]
struct Pointer(*mut u32);
unsafe impl Send for Pointer {}
unsafe impl Sync for Pointer {}

let indices = [1, 4, 7, 8];
let mut arr = [1u32, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let arr_ptr = Pointer(arr.as_mut_ptr());

indices.into_par_iter().for_each(move |x| {
    // safety:
    // * `indices` must be unique and point inside `arr`
    // * `place` must not leak outside the closure
    // * no element of `array` that is in `indices` may be accessed by
    //   some other thread while this is running
    let place = unsafe { &mut *{arr_ptr}.0.add(x) };
    *place = some_function(x);
});

But I'd reserve that kind of thing to use only as last resort. Once you introduce ad-hoc unsafe like this in your code base, you never know when you'll make a misstep and make your program vulnerable to random crashes and corruptions.

user4815162342
  • 141,790
  • 18
  • 296
  • 355