如何使用Rayon并行化ndarray :: Array1切片上的循环?

时间:2019-05-13 12:27:39

标签: rust rayon

我正在实现一个仿真,其中大部分时间都花在循环遍历数组切片上。我想使用人造丝将其并行化。

此示例编译并运行,其中Zip行已被注释掉。我在ndarray-parallel documentation中找到了Zip::from(&mut yc).and(&xc).par_apply

#![allow(non_snake_case)]
#![allow(unused)]

#[macro_use]
extern crate ndarray;

use ndarray::prelude::*;
use ndarray::Zip;

extern crate ndarray_parallel;
use ndarray_parallel::prelude::*;

extern crate rayon;
use rayon::prelude::*;

use std::time::{Duration, Instant};

fn f(x: f64, x0: f64, dx: f64) -> f64 {
    let c = (x - x0) / dx;
    1.0 / (c * c + 1.0)
}

fn serial() {
    let nx = 100000;
    let xmin = 0.0;
    let xmax = 1.0;
    let Dx = (xmax - xmin) / 20.0;
    let x: Array1<f64> = Array::linspace(xmin, xmax, nx);
    let dx = x[1] - x[0];
    let mut y: Array1<f64> = Array1::<f64>::zeros(nx);
    let cc = 2.3;

    for i in 0..nx {
        let x0 = x[i];
        let di = std::cmp::max(2, (Dx / dx * 10.0) as usize);
        let i1 = std::cmp::max(0, i - di);
        let i2 = std::cmp::max(nx - 1, i + di);

        for j in i1..i2 {
            y[i] = y[i] + cc * f(x[i], x0, Dx);
        }
    }
    println!("{}", y.sum());
}

fn parallel() {
    let nx = 100000;
    let xmin = 0.0;
    let xmax = 1.0;
    let Dx = (xmax - xmin) / 20.0;
    let x: Array1<f64> = Array::linspace(xmin, xmax, nx);
    let dx = x[1] - x[0];
    let mut y: Array1<f64> = Array1::<f64>::zeros(nx);
    let cc = 2.3;

    for i in 0..nx {
        let x0 = x[i];
        let di = std::cmp::max(2, (Dx / dx * 10.0) as usize);
        let i1 = std::cmp::max(0, i - di);
        let i2 = std::cmp::min(nx - 1, i + di);

        let mut xc = x.slice(s![i1..i2]);
        let mut yc = y.slice(s![i1..i2]);

        Zip::from(&mut yc).and(&xc).par_apply(|y_, &x_| {
            *y_ = *y_ + cc * f(x_, x0, Dx);
        });
    }

    println!("{}", y.sum());
}

fn main() {
    let t1 = Instant::now();
    serial();
    let t2 = Instant::now();
    parallel();
    let t3 = Instant::now();

    println!("{:?}  {:?}", t2.duration_since(t1), t3.duration_since(t2));
}
[dependencies]
ndarray = "0.12.1"
rayon = "1.0.3"
ndarray-parallel = "0.9.0"
error[E0277]: the trait bound `&mut ndarray::ArrayBase<ndarray::ViewRepr<&f64>, ndarray::Dim<[usize; 1]>>: ndarray::IntoNdProducer` is not satisfied
  --> src/main.rs:65:9
   |
65 |         Zip::from(&mut yc).and(&xc).par_apply(|y_, &x_| {
   |         ^^^^^^^^^ the trait `ndarray::IntoNdProducer` is not implemented for `&mut ndarray::ArrayBase<ndarray::ViewRepr<&f64>, ndarray::Dim<[usize; 1]>>`
   |
   = help: the following implementations were found:
             <&'a mut ndarray::ArrayBase<S, D> as ndarray::IntoNdProducer>
             <&'a ndarray::ArrayBase<S, D> as ndarray::IntoNdProducer>
   = note: required by `<ndarray::Zip<(P,), D>>::from`

我是否理解错误消息是由于数组切片(x.slice(s![i1..i2]))引起的?如果必须复制这些切片,则并行化没有任何意义。

0 个答案:

没有答案