如何满足迭代器特征界限才能在这里使用 Rayon?

urs*_*rei 2 rust rayon

我正在尝试使用 Rayon 的par_iter而不是并行化 Ramer\xe2\x80\x93Douglas-Peucker 线简化算法iter

\n\n
extern crate num_traits;\nuse num_traits::{Float, ToPrimitive};\nextern crate rayon;\nuse self::rayon::prelude::*;\n\n#[derive(PartialEq, Clone, Copy, Debug)]\npub struct Coordinate<T>\n    where T: Float\n{\n    pub x: T,\n    pub y: T,\n}\n\n#[derive(PartialEq, Clone, Copy, Debug)]\npub struct Point<T>(pub Coordinate<T>) where T: Float;\n\nimpl<T> Point<T>\n    where T: Float + ToPrimitive\n{\n    pub fn new(x: T, y: T) -> Point<T> {\n        Point(Coordinate { x: x, y: y })\n    }\n    pub fn x(&self) -> T {\n        self.0.x\n    }\n    pub fn y(&self) -> T {\n        self.0.y\n    }\n}\n\nunsafe impl<T> Send for Point<T> where T: Float {}\nunsafe impl<T> Sync for Point<T> where T: Float {}\n\nfn distance<T>(a: &Point<T>, p: &Point<T>) -> T \n    where T: Float\n{\n    let (dx, dy) = (a.x() - p.x(), a.y() - p.y());\n    dx.hypot(dy)\n}\n\n// perpendicular distance from a point to a line\nfn point_line_distance<T>(point: &Point<T>, start: &Point<T>, end: &Point<T>) -> T\n    where T: Float\n{\n    if start == end {\n        distance(point, start)\n    } else {\n        let numerator = ((end.x() - start.x()) * (start.y() - point.y()) -\n                         (start.x() - point.x()) * (end.y() - start.y()))\n            .abs();\n        let denominator = distance(start, end);\n        numerator / denominator\n    }\n}\n\n// Ramer\xe2\x80\x93Douglas-Peucker line simplification algorithm\nfn rdp<T>(points: &[Point<T>], epsilon: &T) -> Vec<Point<T>>\n    where T: Float + Send + Sync\n{\n    if points.is_empty() {\n        return points.to_vec();\n    }\n    let mut dmax = T::zero();\n    let mut index: usize = 0;\n    let mut distance: T;\n\n    for (i, _) in points.par_iter().enumerate().take(points.len() - 1).skip(1) {\n        distance = point_line_distance(&points[i], &points[0], &*points.last().unwrap());\n        if distance > dmax {\n            index = i;\n            dmax = distance;\n        }\n    }\n    if dmax > *epsilon {\n        let mut intermediate = rdp(&points[..index + 1], &*epsilon);\n        intermediate.pop();\n        intermediate.extend_from_slice(&rdp(&points[index..], &*epsilon));\n        intermediate\n    } else {\n        vec![*points.first().unwrap(), *points.last().unwrap()]\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::{Point};\n    use super::{rdp};\n        #[test]\n    fn rdp_test() {\n        let mut vec = Vec::new();\n        vec.push(Point::new(0.0, 0.0));\n        vec.push(Point::new(5.0, 4.0));\n        vec.push(Point::new(11.0, 5.5));\n        vec.push(Point::new(17.3, 3.2));\n        vec.push(Point::new(27.8, 0.1));\n        let mut compare = Vec::new();\n        compare.push(Point::new(0.0, 0.0));\n        compare.push(Point::new(5.0, 4.0));\n        compare.push(Point::new(11.0, 5.5));\n        compare.push(Point::new(27.8, 0.1));\n        let simplified = rdp(&vec, &1.0);\n        assert_eq!(simplified, compare);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我已经impldSendSyncfor Point<T>,但是当我切换到 时par_iter,出现以下错误:

\n\n
extern crate num_traits;\nuse num_traits::{Float, ToPrimitive};\nextern crate rayon;\nuse self::rayon::prelude::*;\n\n#[derive(PartialEq, Clone, Copy, Debug)]\npub struct Coordinate<T>\n    where T: Float\n{\n    pub x: T,\n    pub y: T,\n}\n\n#[derive(PartialEq, Clone, Copy, Debug)]\npub struct Point<T>(pub Coordinate<T>) where T: Float;\n\nimpl<T> Point<T>\n    where T: Float + ToPrimitive\n{\n    pub fn new(x: T, y: T) -> Point<T> {\n        Point(Coordinate { x: x, y: y })\n    }\n    pub fn x(&self) -> T {\n        self.0.x\n    }\n    pub fn y(&self) -> T {\n        self.0.y\n    }\n}\n\nunsafe impl<T> Send for Point<T> where T: Float {}\nunsafe impl<T> Sync for Point<T> where T: Float {}\n\nfn distance<T>(a: &Point<T>, p: &Point<T>) -> T \n    where T: Float\n{\n    let (dx, dy) = (a.x() - p.x(), a.y() - p.y());\n    dx.hypot(dy)\n}\n\n// perpendicular distance from a point to a line\nfn point_line_distance<T>(point: &Point<T>, start: &Point<T>, end: &Point<T>) -> T\n    where T: Float\n{\n    if start == end {\n        distance(point, start)\n    } else {\n        let numerator = ((end.x() - start.x()) * (start.y() - point.y()) -\n                         (start.x() - point.x()) * (end.y() - start.y()))\n            .abs();\n        let denominator = distance(start, end);\n        numerator / denominator\n    }\n}\n\n// Ramer\xe2\x80\x93Douglas-Peucker line simplification algorithm\nfn rdp<T>(points: &[Point<T>], epsilon: &T) -> Vec<Point<T>>\n    where T: Float + Send + Sync\n{\n    if points.is_empty() {\n        return points.to_vec();\n    }\n    let mut dmax = T::zero();\n    let mut index: usize = 0;\n    let mut distance: T;\n\n    for (i, _) in points.par_iter().enumerate().take(points.len() - 1).skip(1) {\n        distance = point_line_distance(&points[i], &points[0], &*points.last().unwrap());\n        if distance > dmax {\n            index = i;\n            dmax = distance;\n        }\n    }\n    if dmax > *epsilon {\n        let mut intermediate = rdp(&points[..index + 1], &*epsilon);\n        intermediate.pop();\n        intermediate.extend_from_slice(&rdp(&points[index..], &*epsilon));\n        intermediate\n    } else {\n        vec![*points.first().unwrap(), *points.last().unwrap()]\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::{Point};\n    use super::{rdp};\n        #[test]\n    fn rdp_test() {\n        let mut vec = Vec::new();\n        vec.push(Point::new(0.0, 0.0));\n        vec.push(Point::new(5.0, 4.0));\n        vec.push(Point::new(11.0, 5.5));\n        vec.push(Point::new(17.3, 3.2));\n        vec.push(Point::new(27.8, 0.1));\n        let mut compare = Vec::new();\n        compare.push(Point::new(0.0, 0.0));\n        compare.push(Point::new(5.0, 4.0));\n        compare.push(Point::new(11.0, 5.5));\n        compare.push(Point::new(27.8, 0.1));\n        let simplified = rdp(&vec, &1.0);\n        assert_eq!(simplified, compare);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我不明白它在要求什么。问题是我在元组上操作吗?

\n

Seb*_*edl 6

Rayon 的并行迭代器实现ParallelIterator,而不是Iterator。特别是,这意味着您不能只是将 a 放入par_iter()for 循环标头中并期望它突然变得并行。for是顺序的。

由于您的原始代码不是根据迭代器函数编写的,而是根据 for 循环编写的,因此您不能简单地通过切换到来将其并行化par_iter(),而必须实际重新设计代码。

特别是,代码的失败部分似乎是在实现该max_by_key功能。