我正在尝试使用 Rayon 的par_iter而不是并行化 Ramer\xe2\x80\x93Douglas-Peucker 线简化算法iter:
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}\nRun Code Online (Sandbox Code Playgroud)\n\n我已经impldSend和Syncfor Point<T>,但是当我切换到 时par_iter,出现以下错误:
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}\nRun Code Online (Sandbox Code Playgroud)\n\n我不明白它在要求什么。问题是我在元组上操作吗?
\nRayon 的并行迭代器实现ParallelIterator,而不是Iterator。特别是,这意味着您不能只是将 a 放入par_iter()for 循环标头中并期望它突然变得并行。for是顺序的。
由于您的原始代码不是根据迭代器函数编写的,而是根据 for 循环编写的,因此您不能简单地通过切换到来将其并行化par_iter(),而必须实际重新设计代码。
特别是,代码的失败部分似乎是在实现该max_by_key功能。