向量(或向量的向量)上的并发操作

Concurrent operations on a Vector (or Vector of Vectors)

我即将编写一个 Rust 程序,我想在其中实现并发。我的数据将存储在一个 Vector 或 Vector of Vectors 中,以我能使工作最简单的方式为准。下面是一些伪代码,用于显示如何设置结构和向量。显然语法不正确。

struct Artifact
    identifier = "abc123";
    vector_containing_Line_structs = [struct Line, struct Line, struct Line, ..., etc];
    // ^ this vector will contain thousands of line structs

struct Line
    line_type = 1
    speed = 5
    array_length = 4;
    array = {10, 20, 30, 40}

基本上,这就是我目前正在考虑的存储数据的方式(对想法持开放态度)。在程序的后面,我想使用多线程并发地对 vector_containing_Line_structs 向量的子集执行计算。 Thread1 在索引 0-10000 上运行,thread2 在索引 10001-20000 上运行,等等。线程是只读的,它们不会将任何内容写回 Line 结构,只是访问数组和每个结构中的结构 'variables' .

rust 编译器会让不同的线程同时操作同一个 vector 中的项目吗?或者,有没有一种方法可以拆分这些数据,以便以保留 order/indexing 并允许以类似方式进行并发计算的方式组织它?

-- 我唯一的另一个想法是向量的向量。 vector some_vector = [ [10k Line structs], [10k Line Structs], ... ]。我希望 Rust 让我将每个子向量分配给不同的线程。

由于您的问题不是特定于结构的成员,而是关于跨多个线程从共享向量读取数据的能力, 这是一个处理简单整数向量的简单示例。

不能将引用或切片直接传递给线程,因为编译器无法证明引用的数据比线程的寿命更长。 然后我们使用 Arc 只要线程存在就会使这些数据保持活动状态。

从线程中获取部分结果通常使用 mpsc channel

参见documentation

fn main() {
    // prepare vector to be shared
    let mut data = Vec::new();
    for i in 0..10_000 {
        data.push(i);
    }
    // make it accessible to multiple threads
    let data = std::sync::Arc::new(data);
    // prepare communication channel
    let (tx, rx) = std::sync::mpsc::channel();
    // launch the desired number of threads
    let thread_count = 8;
    let mut threads = Vec::new();
    for idx in 0..thread_count {
        // clone shared ressources in order to move them into the thread
        let tx = tx.clone();
        let data = data.clone();
        threads.push(std::thread::spawn(move || {
            // determine the part of shared data to be accessed by this thread
            let begin = data.len() * idx / thread_count;
            let end = data.len() * (idx + 1) / thread_count;
            let slc = &data[begin..end];
            // work on this slice
            let mut sum = 0;
            for v in slc {
                sum += v;
            }
            println!("thread {} --> {}", idx, sum);
            // send a result to main thread
            tx.send(sum).unwrap();
        }));
    }
    // wait for threads and collect results
    let mut result = 0;
    for th in threads {
        result += rx.recv().unwrap();
        th.join().unwrap();
    }
    println!("done: {}", result);
}