I have an algorithm (its details are not important) that evaluates a vector step by step. Each new value in the vector is a result of calculations over several old ones, such that new values can be calculated independently or parallelly. The size of the vector is supposed to be large (thousands or millions). So on each step I represent the vector as chunks and I spawn a thread for each chunk. After the calculations in the threads I save the result back into the vector.
This is the code I tried:
// Options
let size = 20;
let win = 3;
let threads_num = 6;
// Array
let mut arr = vec![10; size];
// Evaluating
for _step in 0..2 {
// Array Arc. How do I avoid copying here???
let arr_arc = std::sync::Arc::new(arr.clone());
// Threads vector
let mut threads = Vec::new();
// Loop for threads
for tix in 0..threads_num {
// Extract array
let arr = std::sync::Arc::clone(&arr_arc);
// Range for the chunk
let j_from = tix * (size + threads_num - 1) / threads_num;
let j_to = std::cmp::min(
(tix + 1) * (size + threads_num - 1) / threads_num,
size
);
// New thread
let thread = std::thread::spawn(move || {
// Calculations for each element in the chunk
let mut res = vec![0; j_to - j_from];
for j in j_from..j_to {
let i_from = j.checked_sub(win).unwrap_or(0);
let i_to = std::cmp::min(size, j + win + 1);
for i in i_from..i_to {
res[j - j_from] += arr[i];
}
}
// Return the result chunk and the range
(res, j_from, j_to)
});
threads.push(thread);
}
// Copying the result from the chunk back to arr
// Can I avoid copying here maybe???
for thread in threads.into_iter() {
let (res, j_from, j_to) = thread.join().unwrap();
arr[j_from..j_to].clone_from_slice(&res);
}
}
// Print the result
println!("{:?}", arr);
It works correct but it seems to be inefficient because of extra copying in the line let arr_arc = std::sync::Arc::new(arr.clone());
. I tried to avoid copying by using another vector arr_res
defined outside the step-loop like this:
let mut arr = std::sync::Arc::new(vec![10; size]);
let mut arr_res = std::sync::Arc::new(vec![10; size]);
for _step in 0..2 {
...
// This memory exchanging avoids copying!
std::mem::swap(&mut arr, &mut arr_res);
}
But Arc-objects can’t be swapped, an error happens.
So is there a way to avoid copying in my case? The lines where I think, the copying can be optimized, I marked in the comments.
1