使用非重叠的矢量块,并组合结果

时间:2015-06-29 16:51:04

标签: multithreading parallel-processing rust

我试图通过使用线程来加速对大型向量的昂贵计算。我的函数使用向量,计算新值的向量(它不会聚合,但必须保留输入顺序),并返回它。但是,我正在努力弄清楚如何生成线程,为每个线程分配矢量切片,然后收集并合并结果。

// 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吗?

1 个答案:

答案 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()