I am trying to write a concurrent finder function for vectors, that under the hood splits the Vec
into parts and uses a thread for each part. Every thread iterates over its own piece of the array and if it finds element it should stop the main function. For a vector 0..n
and 4 threads:
thread1: iterate over 0..(n/4)
thread2: iterate over n/4..(n/2)
thread3: iterate over n/2..(n/2 +(n/4))
thread3: iterate over (n/2 +(n/4))..n
This is my implementation. It works, but is not what I want:
use std::thread;
fn finder(ref arr:&Vec<i32>, start:i32, end:i32, find:i32) {
// for simplification
for c in start..end {
if c == find {
println!("Boom!");
}
}
}
fn main() {
let array_init:Vec<i32> = (1..10_000_001).collect();
let part = 2500000;
let f_number = 9875640;
let handles: Vec<_> = (1..4).map(|num| {
let array = array_init.clone();
thread::spawn(move || {
finder(&array, (num * part), ((num + 1) * part), f_number);
})
}).collect();
for h in handles {
h.join().unwrap();
}
}
This version is slower than the non-concurrent finder function. The problem is this line: let array = array_init.clone();
Every thread makes a copy of the initial array. For massive vectors, this operation is expensive.
I have two questions:
What is the Rust way to solve this problem, using only one vector without copies?
The initial array is an immutable resource, why can't I share it between threads like this:
let array_init:Vec<i32> = (1..10_000_001).collect(); let part = 2500000; let f_number = 9875640; let handles: Vec<_> = (1..4).map(|num| { thread::spawn(move || { finder(&array_init, (num * part), ((num + 1) * part), f_number); }) }).collect(); for h in handles { h.join().unwrap(); }