程序仍然在使用 par_iter 和 par_extend 的一个线程上运行

Program still runs on one thread using par_iter and par_extend

我正在尝试并行化我的一部分代码,尽管它使用 rayon 和并行迭代器 par_iter()par_extend(),但它看起来仍然运行在单线程。

我只是创建了一个 i32 向量,用很多值填充它,然后将这些值移动到 collections::HashSet 整数中。

我的单线程代码:

use std::collections::HashSet;

fn main() {
    let my_vec: Vec<i64> = (0..100_000_000).collect();

    let mut my_set: HashSet<i64> = HashSet::new();
    let st = std::time::Instant::now();
    my_set.extend(
        my_vec.iter().map(|x| x*(x+3)/77+44741)  // this is supposed to take a while to compute
    );
    let dur = st.elapsed();
    println!("{:?}", dur);

}

运行 时间平均在 8.86 s 左右。 下面是使用并行迭代器的代码:

extern crate rayon;
use rayon::prelude::*;
use std::collections::HashSet;

fn main() {
    let my_vec: Vec<i64> = (0..100_000_000).collect();

    let mut my_set: HashSet<i64> = HashSet::new();
    let st = std::time::Instant::now();
    my_set.par_extend(
        my_vec.par_iter().map(|x| x*(x+3)/77+44741) // this is supposed to take a while to compute
    );
    let dur = st.elapsed();
    println!("{:?}", dur);
}

'parallel'版本的平均运行时间几乎相同(8.62 s),cpu监视器清楚地显示单个cpu 正在 100% 工作,而其他人只是等待。

你知道我哪里做错了,或者没看懂吗?

你的模拟是不正确的,因为你的计算实际上很快,快到比线程上下文切换快几个数量级。您的核心处于 100% 可能是人造丝运行时,而其他核心正在等待它。

如果你真的用睡眠代替你的计算,结果如你所料:

use std::collections::HashSet;
use rayon::prelude::*; // 1.1.0
use std::time::Duration;

fn main() {
    fn slow(i: &i64) -> i64 {
        std::thread::sleep(Duration::from_millis(5));

        *i
    }

    let my_vec: Vec<i64> = (0..100).collect();

    let mut my_set: HashSet<i64> = HashSet::new();

    let st = std::time::Instant::now();
    my_set.extend(
        my_vec.iter().map(slow)  // this is supposed to take a while to compute
    );
    let dur = st.elapsed();
    println!("Regular: {:?}", dur);

    let st = std::time::Instant::now();
    my_set.par_extend(
        my_vec.par_iter().map(slow) // this is supposed to take a while to compute
    );
    let dur = st.elapsed();
    println!("Rayon: {:?}", dur);
}

输出:

Regular: 685.670791ms
Rayon: 316.733253ms

当您尝试优化您的代码时,您必须仔细地对其进行基准测试,因为有时,当您并行化您的代码时,这会使它变慢。