如何使用 Rust 使用从 1 到 1000000 的并发性进行求和?



我是 Rust 的新手,我想用并发来总结大量的数字。我找到了这个代码:

use std::thread;
use std::sync::{Arc, Mutex};
static NTHREAD: usize = 10;
fn main() {
let mut threads = Vec::new();
let x = 0;
// A thread-safe, sharable mutex object
let data = Arc::new(Mutex::new(x));
for i in 1..(NTHREAD+1) {
// Increment the count of the mutex
let mutex = data.clone();
threads.push(thread::spawn(move || {
// Lock the mutex
let n = mutex.lock();
match n {
Ok(mut n) => *n += i,
Err(str) => println!("{}", str)
}
}));
}
// Wait all threads ending
for thread in threads {
let _ = thread.join().unwrap();
}
assert_eq!(*data.lock().unwrap(), 55);
}

这在线程为 10 时有效,但在线程大于 20 时不起作用。

我认为在任何数量的线程中都应该没问题。

我误解了什么吗?有没有另一种方法可以用并发从 1 到 1000000 求和?

提供的代码存在几个问题。

  1. thread::spawn创建一个操作系统级别的线程,这意味着现有代码不可能扩展到标题中指示的多达一百万的数字。这将需要一百万个线程并行,而典型的现代操作系统最多支持几千个线程。更受限制的环境,例如嵌入式系统或虚拟/半虚拟机,允许的比这少得多;例如,Rust 操场似乎最多允许 24 个并发线程。相反,需要创建一个固定的少量线程,并仔细地在它们之间分配工作。
  2. 在每个线程中执行的函数在锁内运行,从而有效地序列化线程完成的工作。即使可以生成任意多个线程,编写的循环执行速度也不会比单个线程执行的速度快 - 并且在实践中它会慢几个数量级,因为它会花费大量时间锁定/解锁严重争用的互斥锁。

Boiethios 的评论中提供了在手动管理线程的同时解决此类问题的一种好方法:如果您有 4 个线程,只需将 1..250k、250k 的总和。500k等,然后汇总线程函数的返回。

还是有另一种方法可以用并发从 1 到 1000000 求和?

我建议使用更高级别的库来封装工作线程的创建/池化以及它们之间的工作分工。Rayon是一个很好的,提供了一个"并行迭代"工具,它的工作方式类似于迭代,但自动在多个内核之间分配工作。使用 Rayon,整数的并行求和如下所示:

extern crate rayon;
use rayon::prelude::*;
fn main() {
let sum: usize = (1..1000001).collect::<Vec<_>>().par_iter().sum();
assert_eq!(sum, 500000500000);
}

最新更新