我应该如何为并行计算生成线程?
今天,我进入了多线程。 由于这是一个新概念,我认为我可以通过将简单迭代转换为并行化迭代来开始学习。 但是,我想我在开始之前就陷入了困境。
最初,我的循环看起来像这样:
let stuff: Vec<u8> = items.into_iter().map(|item| {
some_item_worker(&item)
}).collect();
我已经将相当大量的东西放入了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
我有一个四核CPU,这意味着我最多只能同时运行4个线程。 我猜想它是这样工作的:一旦迭代器启动,线程就会产生。 每当一个线程结束时,另一个线程开始,以便在任何给定的时间,4个线程同时运行。
结果是它花了(在一些重新运行后)〜0.2秒来完成相同的计算。 显然,这里没有并行计算。 我不知道为什么时间增加了4倍,但我相信我误解了一些东西。
由于这不是正确的方法,我应该如何修改程序以便线程同时执行?
编辑:
对不起,我错了〜0.2秒。 我醒来后再次尝试,当我发现通常的迭代运行了2秒。 事实证明,一些进程一直在疯狂地占用内存。 当我重新启动我的系统并再次尝试线程迭代时,它运行了大约0.07秒。 这是每次运行的一些时间。
实际迭代(第一个):
0.0553760528564 seconds
0.0539519786835 seconds
0.0564560890198 seconds
螺纹一:
0.0734670162201 seconds
0.0727820396423 seconds
0.0719120502472 seconds
我同意这些线程确实同时运行,但似乎要花费20毫秒才能完成这项工作。 我的实际目标是利用我的处理器并行运行线程并尽快完成工作。 这会变得复杂吗? 我该怎么做才能让这些线程并行运行,而不是并发?
我有一个四核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()
}
}
如果你运行这个,你会看到“开始!” 打印500次,然后是500“Finished!”
显然,这里没有并行计算
不幸的是,你的问题没有充分说明你为什么要花时间。 在我提供的例子中,它需要少于600毫秒,所以它显然不会在串行中发生!
创建线程有成本。 如果线程内部的计算成本足够小,则线程成本或线程造成的效率低下将会使其变得更加糟糕。
例如,产生1000万个线程来翻倍1000万个u8s可能不值得。 向量化它可能会产生更好的性能。
也就是说,通过并行化廉价任务,您仍然可以获得一些改进。 但是你希望通过一个线程池使用更少的线程,这个线程池有少量的线程(所以你可以在任何给定的点上创建一个(很少的)线程数量,减少CPU争用)或者更复杂的东西(引擎盖下,api很简单)就像人造丝一样。
// Notice `.par_iter()` turns it into a `parallel iterator`
let stuff: Vec<u8> = items.par_iter().map(|item| {
some_item_worker(&item)
}).collect();
链接地址: http://www.djcxy.com/p/35391.html
上一篇: How should I spawn threads for parallel computation?
下一篇: How does the getModifiers() method calculate the value for multiple modifiers?