Rust 锈蚀的安全并行高斯消除

Rust 锈蚀的安全并行高斯消除,rust,parallel-processing,linear-algebra,Rust,Parallel Processing,Linear Algebra,我正在尝试并行化高斯消去法的实现。我知道像人造丝这样的板条箱可能会使这更容易,但我的目标是使用基于mpsc::channel的实现,所以我选择使用 下面是代码库的概述。有些特性是多余的,但是这段代码是从C移植的,所以我试图维护这个结构 传递的数据结构包含矩阵的大小(冗余)、矩阵、四个验证向量(用于确定正确性)和线程数: pub struct Data { pub nsize: usize, pub matrix: Vec<Vec<f64>>, pu

我正在尝试并行化高斯消去法的实现。我知道像人造丝这样的板条箱可能会使这更容易,但我的目标是使用基于mpsc::channel的实现,所以我选择使用

下面是代码库的概述。有些特性是多余的,但是这段代码是从C移植的,所以我试图维护这个结构

传递的数据结构包含矩阵的大小(冗余)、矩阵、四个验证向量(用于确定正确性)和线程数:

pub struct Data {
    pub nsize: usize,
    pub matrix: Vec<Vec<f64>>,
    pub b: Vec<f64>,
    pub c: Vec<f64>,
    pub v: Vec<f64>,
    pub swap: Vec<u64>,
    pub num_threads: usize,
}
pivot(矩阵,索引)
函数会改变数据中的矩阵

我当前的并行高斯实现:

pub fn compute_gauss_p(data: Data) -> Data {
    let num_threads = data.num_threads;
    let pool = ThreadPool::new(data.num_threads);
    let nsize = data.nsize;
    let sdata = Arc::new(data);

    for i in 0..nsize {
        pivot(&mut *sdata, i); //compile error, as Arc does not implement DerefMut
        for n in 0..num_threads {
            let sdatacpy = Arc::clone(&sdata);
            pool.execute(move || {
                do_calc(sdatacpy, i + n);
            });
        }
        pool.join();
    }

    Arc::try_unwrap(sdata).unwrap()
}
fn do_calc(数据:Arc,i:usize){//无法从Arc解除mut的防护
让我们一起旋转;
设num_threads=data.num_threads;
对于j in(i+1..data.matrix.len()).step_by(num_threads){
pivot_val=data.matrix[j][i];
数据.矩阵[j][i]=0.0;
对于i+1..data.matrix.len()中的k{
data.matrix[j][k]=pivot_val*data.matrix[i][k];
}
data.b[j]=pivot_val*data.b[i];
}
}
我曾考虑过使用互斥来独占矩阵,但这会使工作顺序化。 我的下一个想法是将矩阵视为互斥体的向量,每个互斥体包含一行。这将使我能够分配工作。矩阵将是:

Vec<Mutex<Vec<f64>>>
Vec

然而,我想知道这是否是正确的道路。我希望避免使用不安全的指针引用(我可以使用我的C版本),同时继续使用具有mpsc::channel的范例(没有人造丝或其他不使用通道的库)。

这是我认为不安全代码是获得性能的唯一途径的领域之一。通常,矩阵以列主格式或行主格式实现为单个数组。使用数组的数组会导致内存不连续和性能降低。为了在这里构建有效的算法,您必须同时对数组的多个字段进行变异。互斥体数组是一种解决方案,但速度很慢,因为您可以在没有数据竞争的情况下构建算法,因此您会留下不安全的代码。另见:
fn do_calc(data: Arc<Data>, i: usize) { //cannot derefence mut from Arc
    let mut pivot_val;
    let num_threads = data.num_threads; 
    for j in (i + 1..data.matrix.len()).step_by(num_threads) {
        pivot_val = data.matrix[j][i];
        data.matrix[j][i] = 0.0;
        for k in i + 1..data.matrix.len() {
            data.matrix[j][k] -= pivot_val * data.matrix[i][k];
        }
        data.b[j] -= pivot_val * data.b[i];
    }
}
Vec<Mutex<Vec<f64>>>