Я пытаюсь написать функцию, которая вычисляет матрицы расстояний, используя ndarray
:
extern crate ndarray;
use ndarray::{s, Array2, ArrayView1, indices_of, azip, array};
use ndarray::parallel::par_azip;
use std::f64;
type M = Array2<f64>;
fn main() {
// make some arbitrary data
let points = array!([0.,23.], [12., 13.], [15., 2.], [16., 145.], [42., 11.], [12., 12.], [11., 12.], [56., 18.], [34., 12.]);
// calculate matrix
let dist_arr = dist_to_mat(&points, &l2);
println!("{}", dist_arr.mapv(|x| (100. * x).round() / 100.))
}
// as an example, use l2 distance
fn l2(x: &ArrayView1<f64>, y: &ArrayView1<f64>) -> f64 {
let diff = x - y;
let result = (&diff * &diff).sum();
return result.sqrt()
}
pub fn dist_to_mat(
points: &Array2<f64>,
dist_fn: &dyn Fn(&ArrayView1<f64>, &ArrayView1<f64>) -> f64,
) -> M {
// initialize array
let mut distances = Array2::zeros((points.nrows(), points.nrows()));
let idx = indices_of(&distances);
// helper function to get the entries of points
let func = |i: usize, j: usize| -> f64 {
dist_fn(&points.slice(s![i, ..]), &points.slice(s![j, ..]))
};
// apply function to matrix with index array in lock-step
par_azip!((c in &mut distances, (i,j) in idx){*c = func(i,j)}); // <- error here; works if par_azip is replaced with azip.
return distances
}
Хотя это нормально работает с однопоточным azip
, с par_azip
Я получаю ошибку:
`dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64` cannot be shared between threads safely
`dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64` cannot be shared between threads safely
help: within `[closure@<::ndarray::zip::zipmacro::azip macros>:23:6: 23:7 func:&[closure@src/main.rs:27:16: 29:6 dist_fn:&&dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64, points:&&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 2]>>]]`, the trait `std::marker::Sync` is not implemented for `dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64`
note: required because it appears within the type `&dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64`
note: required because it appears within the type `&&dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64`
note: required because it appears within the type `[closure@src/main.rs:27:16: 29:6 dist_fn:&&dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64, points:&&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 2]>>]`
note: required because it appears within the type `&[closure@src/main.rs:27:16: 29:6 dist_fn:&&dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64, points:&&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 2]>>]`
note: required because it appears within the type `[closure@<::ndarray::zip::zipmacro::azip macros>:23:6: 23:7 func:&[closure@src/main.rs:27:16: 29:6 dist_fn:&&dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64, points:&&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 2]>>]]`rustc(E0277)
<::ndarray::parallel::zipmacro::par_azip macros>(1, 50): `dyn for<'r, 's, 't0, 't1> std::ops::Fn(&'r ndarray::ArrayBase<ndarray::ViewRepr<&'s f64>, ndarray::Dim<[usize; 1]>>, &'t0 ndarray::ArrayBase<ndarray::ViewRepr<&'t1 f64>, ndarray::Dim<[usize; 1]>>) -> f64` cannot be shared between threads safely
Какой объект нельзя безопасно разделить между потоками: возвращаемое значение dist_fun
или dist_fun
? Как мне это исправить?