我正在尝试为向量编写并发查找器函数,在引擎盖下将Vec
分成几部分并为每个部分使用一个线程。每个线程迭代它自己的数组,如果找到元素,它应该停止main函数。对于向量0..n
和4个线程:
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
这是我的实施。它有效,但不是我想要的:
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();
}
}
此版本比非并发查找程序功能慢。问题是这一行:let array = array_init.clone();
每个线程都会生成初始数组的副本。对于大型载体,这种操作很昂贵。
我有两个问题:
什么是解决此问题的Rust方法,只使用一个没有副本的向量?
初始数组是一个不可变资源,为什么我不能在这样的线程之间共享它:
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();
}