【问题标题】:Do i have to create a copy of objects for threads need [duplicate]我是否必须为线程需要创建对象的副本[重复]
【发布时间】:2021-02-22 21:02:28
【问题描述】:

我创建了两种方法,一种是同步的,一种是多线程的,因为我想比较性能同步和并行方法。但是每次当我想在线程中使用我的数据时,我都会遇到一个问题,即使我知道要删除它们直到此方法结束,我也必须先复制它们。如果我在线程中使用之前没有复制这些数据,那么我会收到一个错误,我必须让我的数据'static:

fn parallel_kronecker_product(&self, matrix: &Matrix) -> Matrix {
    let product_rows = self.rows_count * matrix.rows_count;
    let product_columns_count = self.columns_count * matrix.columns_count;
    let product = Arc::new(Mutex::new(Matrix::new_zeros_matrix(
        product_rows,
        product_columns_count,
    )));
    let mut handles = vec![];
    for m1_row_index in 0..self.rows_count {
        let product = Arc::clone(&product);
        let matrix_a = self.to_owned();
        let matrix_b = matrix.to_owned();
        handles.push(
            thread::spawn(move || {
                for m1_column_index in 0..matrix_a.columns_count {
                    for m2_row_index in 0..matrix_b.rows_count {
                        for m2_column_index in 0..matrix_b.columns_count {
                            let product_row_index = m1_row_index * matrix_b.rows_count + m2_row_index;
                            let product_column_index =
                                m1_column_index * matrix_b.columns_count + m2_column_index;
                            let mut prod = product.lock().unwrap();
                            (*prod)[product_row_index][product_column_index] = matrix_a[m1_row_index]
                                [m1_column_index]
                                * matrix_b[m2_row_index][m2_column_index];
                        }
                    }
                }
            })
        );
    }
    for handle in handles {
        handle.join().unwrap();
    }
    return product.lock().unwrap().clone();
}

所以这里我有两个矩阵。基数是不可变的self 和一个来自参数matrix。在for m2_row_index in 0..matrix_b.rows_count 循环内,我只是将一些不会改变原始数据的数据相乘。然后我遍历所有线程来告诉 rust 等到所有线程完成他们的工作,所以这个方法范围之外的任何东西都应该放弃这个matrix

你能告诉我,我能做些什么来不复制这些数据?

【问题讨论】:

  • 彼得的回答显示了如何将链接问题的答案应用于您的案例。如果这不是您要找的东西,请edit 这个问题解释它的不同之处。谢谢!

标签: multithreading rust


【解决方案1】:

您可以使用来自第三方 crate 的作用域线程。有几个可供选择,但一个受欢迎的来自crossbeam。需要这样做的原因是,用于使用std::thread::spawn 生成的线程的类型不携带有关它们持续多长时间的信息,即使您明确加入它们也是如此。 Crossbeam 的作用域线程绑定到周围 Scope 的生命周期,因此借用检查器可以确保它们在作用域结束时完成了借用数据。

您提供的代码缺少很多定义,所以我没有尝试编译它,但总体思路是这样的:

fn parallel_kronecker_product(&self, matrix: &Matrix) -> Matrix {

    // Create a new thread scope and make it own the locals
    thread::scope(move |scope| {
        let product_rows = self.rows_count * matrix.rows_count;
        let product_columns_count = self.columns_count * matrix.columns_count;
        let product = Arc::new(Mutex::new(Matrix::new_zeros_matrix(
            product_rows,
            product_columns_count,
        )));

        let mut handles = vec![];
        for m1_row_index in 0..self.rows_count {
            let product = Arc::clone(&product);
            let matrix_a = self.to_owned();
            let matrix_b = matrix.to_owned();

            // spawn a new thread inside the scope which owns the data it needs to borrow
            handles.push(scope.spawn(move |_| {
                for m1_column_index in 0..matrix_a.columns_count {
                    for m2_row_index in 0..matrix_b.rows_count {
                        for m2_column_index in 0..matrix_b.columns_count {
                            let product_row_index =
                                m1_row_index * matrix_b.rows_count + m2_row_index;
                            let product_column_index =
                                m1_column_index * matrix_b.columns_count + m2_column_index;
                            let mut prod = product.lock().unwrap();
                            (*prod).ind();
                        }
                    }
                }
            }));
        }
        for handle in handles {
            handle.join().unwrap();
        }

        // probably need a new local binding here. For... reasons...
        let product = product.lock().unwrap().clone();
        product
    }).unwrap()
}

【讨论】:

  • 那行得通,我会进一步了解这个库。谢谢你的朋友:D
猜你喜欢
  • 2012-05-31
  • 2015-09-14
  • 1970-01-01
  • 2012-11-21
  • 2012-09-08
  • 2011-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多