我试图通过使用线程来加速对大型向量的昂贵计算。我的函数使用向量,计算新值的向量(它不会聚合,但必须保留输入顺序),并返回它。但是,我正在努力弄清楚如何生成线程,为每个线程分配矢量切片,然后收集并合并结果。
// tunable
const NUMTHREADS: i32 = 4;
fn f(val: i32) -> i32 {
// expensive computation
let res = val + 1;
res
}
fn main() {
// choose an odd number of elements
let orig = (1..14).collect::<Vec<i32>>();
let mut result: Vec<Vec<i32>> = vec!();
let mut flat: Vec<i32> = Vec::with_capacity(orig.len());
// split into slices
for chunk in orig.chunks(orig.len() / NUMTHREADS as usize) {
result.push(
chunk.iter().map(|&digit|
f(digit)).collect()
);
};
// flatten result vector
for subvec in result.iter() {
for elem in subvec.iter() {
flat.push(elem.to_owned());
}
}
println!("Flattened result: {:?}", flat);
}
线程计算应该在for chunk…
和// flatten …
之间进行,但我找不到许多产生x个线程的简单例子,按顺序分配块,并返回新计算的向量离开螺纹并进入容器,因此可以展平。我是否必须在orig.chunks()
中包裹Arc
,并在循环中手动抓取每个块?我必须将f
传递给每个帖子吗?我是否必须使用B树来确保输入和输出顺序匹配?我可以使用simple_parallel
吗?
答案 0 :(得分:2)
嗯,这是不稳定的thread::scoped()
:
Orders Revenue OrderType Date
139 1383.05 Type1 2015-05-01
3 29.85 Type1 2015-06-01
它不稳定,不太可能以这种形式稳定,因为它有一个固有的缺陷(你可以找到更多here)。据我所知,#![feature(scoped)]
use std::thread::{self, JoinGuard};
// tunable
const NUMTHREADS: i32 = 4;
fn f(val: i32) -> i32 {
// expensive computation
let res = val + 1;
res
}
fn main() {
// choose an odd number of elements
let orig: Vec<i32> = (1..14).collect();
let mut guards: Vec<JoinGuard<Vec<i32>>> = vec!();
// split into slices
for chunk in orig.chunks(orig.len() / NUMTHREADS as usize) {
let g = thread::scoped(move || chunk.iter().cloned().map(f).collect());
guards.push(g);
};
// collect the results
let mut result: Vec<i32> = Vec::with_capacity(orig.len());
for g in guards {
result.extend(g.join().into_iter());
}
println!("Flattened result: {:?}", result);
}
只是这种方法的延伸 - 它隐藏了simple_parallel
的摆弄,也可以用于稳定的Rust(可能有一些JoinGuards
ty,I相信)。但是,不建议将其用于一般用途,正如其文档所示。
当然,您可以使用unsafe
,但是您需要克隆每个块,以便将其移动到每个线程中:
thread::spawn()