我应该如何为并行计算生成线程?

Waf*_*nut 2 concurrency multithreading rust

今天,我进入了多线程。由于这是一个新概念,我想我可以通过将简单的迭代转换为并行化的迭代来开始学习。但是,我想我还没开始就被卡住了。

最初,我的循环看起来像这样:

let stuff: Vec<u8> = items.into_iter().map(|item| {
    some_item_worker(&item)
}).collect();
Run Code Online (Sandbox Code Playgroud)

我放入了相当多的东西items,完成计算花了大约 0.05 秒。所以,当我成功实现多线程后,看到时间减少了,我真的很兴奋!

当我使用线程时,我遇到了麻烦,可能是由于我的推理错误。

use std::thread;

let threads: Vec<_> = items.into_iter().map(|item| {
    thread::spawn(move || {
        some_item_worker(&item)
    })
}).collect(); // yeah, this is followed by another iter() that unwraps the values
Run Code Online (Sandbox Code Playgroud)

我有一个四核 CPU,这意味着我最多只能同时运行 4 个线程。我猜它是这样工作的:一旦迭代器启动,就会产生线程。每当一个线程结束时,另一个线程就会开始,因此在任何给定时间,4 个线程同时运行。

结果是(经过一些重新运行后)完成相同的计算需要大约 0.2 秒。显然,这里没有并行计算。我不知道为什么时间增加了 4 倍,但我确定我误解了一些东西。

由于这不是正确的方法,我应该如何修改程序以便线程并发执行?

编辑:

对不起,我错了~0.2 秒。当我注意到通常的迭代运行了 2 秒时,我醒来并再次尝试。原来,某个进程一直在疯狂地消耗内存。当我重新启动系统并再次尝试线程迭代时,它运行了大约 0.07 秒。以下是每次运行的一些时间。

实际迭代(第一个):

let stuff: Vec<u8> = items.into_iter().map(|item| {
    some_item_worker(&item)
}).collect();
Run Code Online (Sandbox Code Playgroud)

螺纹一:

use std::thread;

let threads: Vec<_> = items.into_iter().map(|item| {
    thread::spawn(move || {
        some_item_worker(&item)
    })
}).collect(); // yeah, this is followed by another iter() that unwraps the values
Run Code Online (Sandbox Code Playgroud)

我同意这些线程确实是同时运行的,但它似乎又要消耗 20 毫秒才能完成这项工作。我的实际目标是利用我的处理器并行运行线程并尽快完成工作。这会很复杂吗?我应该怎么做才能使这些线程并行运行,而不是并发运行?

She*_*ter 5

我有一个四核 CPU,这意味着我最多只能同时运行 4 个线程。

可能只有 4 个同时运行,但您当然可以创建 4 个以上......

每当一个线程结束时,另一个线程就会开始,因此在任何给定时间,4 个线程同时运行(这只是一个猜测)。

每当你有一个猜测时,你应该创建一个实验来确定你的猜测是否正确。这是一个:

use std::{iter, thread, time::Duration};

fn main() {
    let items: Vec<_> = iter::repeat(0).take(500).collect();

    let threads: Vec<_> = items
        .into_iter()
        .map(|_| {
            thread::spawn(move || {
                println!("Started!");
                thread::sleep(Duration::from_millis(500));
                println!("Finished!");
            })
        })
        .collect();

    for handle in threads {
        handle.join().unwrap()
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你运行这个,你会看到“Started!” 被打印出 500 次,然后是 500 次“完成!”

显然,这里没有并行计算

不幸的是,您的问题不够详尽,我们无法说明您的时间为什么会增加。在我提供的示例中,它花费的时间不到 600 毫秒,所以它显然不是连续发生的!