I need a way to write to an array with multiple threads, but without mutexes because I need maximum performance.
My algorithm guarantees that the accessed indices are unique. I've spent the last 8 hours trying to find out how to do this, so any help would be very much appreciated.
I'm also I still don't really grok how "Cell", "Arc" and so on work because I'm new to the language.
This is what I found out, but I don't really know how to make it work:
struct UnsafeContainer<T> {
data: UnsafeCell<T>,
}
impl<T> UnsafeContainer<T> {
fn new(data: T) -> UnsafeContainer<T> {
UnsafeContainer {
data: UnsafeCell::new(data),
}
}
}
unsafe impl<T> Sync for UnsafeContainer<T> {}
unsafe impl<T> Send for UnsafeContainer<T> {}
pub fn caller(arr: &mut [i32]) {
let mut buf: Vec<i32> = vec![0; arr.len()]
do_something(&mut arr[..arr.len()/2], &mut arr[arr.len()/2..], &mut buf[..], 8);
}
fn do_something(arr1: &[i32], arr2: &[i32], arr3: &'static mut [i32], num_cores: usize) {
let mut children = Vec::new();
let shared = Arc::new(UnsafeContainer::new(arr3));
for i in 0..num_cores {
let container = shared.clone();
children.push(thread::spawn(move || unsafe {
println!("{:?}", container.data.get());
// I really want to read from one of the arrays here and write to arr3
}));
}
for child in children {
child.join();
}
}
I added the static because the compiler told me to add it, but then I have to add it to the method that calls this, and so on until I'm not able to add static anymore. This is probably a really stupid question due to me not understanding Rust's type system, but I would be very thankful if you could help.
Edit: I also tried with Rayon, but that gives me arr1 is a & reference, so the data it refers to cannot be borrowed as mutable
. Besides, by using this crate, won't it somehow use mutexes under the hood? That would defeat the purpose of my algorithm.