rust - 如何满足 Iterator trait bound 以便在这里使用 Rayon?

标签 rust rayon

我正在尝试使用 Rayon 的 par_iter 并行化 Ramer–Douglas-Peucker 线简化算法而不是 iter :

extern crate num_traits;
use num_traits::{Float, ToPrimitive};
extern crate rayon;
use self::rayon::prelude::*;

#[derive(PartialEq, Clone, Copy, Debug)]
pub struct Coordinate<T>
    where T: Float
{
    pub x: T,
    pub y: T,
}

#[derive(PartialEq, Clone, Copy, Debug)]
pub struct Point<T>(pub Coordinate<T>) where T: Float;

impl<T> Point<T>
    where T: Float + ToPrimitive
{
    pub fn new(x: T, y: T) -> Point<T> {
        Point(Coordinate { x: x, y: y })
    }
    pub fn x(&self) -> T {
        self.0.x
    }
    pub fn y(&self) -> T {
        self.0.y
    }
}

unsafe impl<T> Send for Point<T> where T: Float {}
unsafe impl<T> Sync for Point<T> where T: Float {}

fn distance<T>(a: &Point<T>, p: &Point<T>) -> T 
    where T: Float
{
    let (dx, dy) = (a.x() - p.x(), a.y() - p.y());
    dx.hypot(dy)
}

// perpendicular distance from a point to a line
fn point_line_distance<T>(point: &Point<T>, start: &Point<T>, end: &Point<T>) -> T
    where T: Float
{
    if start == end {
        distance(point, start)
    } else {
        let numerator = ((end.x() - start.x()) * (start.y() - point.y()) -
                         (start.x() - point.x()) * (end.y() - start.y()))
            .abs();
        let denominator = distance(start, end);
        numerator / denominator
    }
}

// Ramer–Douglas-Peucker line simplification algorithm
fn rdp<T>(points: &[Point<T>], epsilon: &T) -> Vec<Point<T>>
    where T: Float + Send + Sync
{
    if points.is_empty() {
        return points.to_vec();
    }
    let mut dmax = T::zero();
    let mut index: usize = 0;
    let mut distance: T;

    for (i, _) in points.par_iter().enumerate().take(points.len() - 1).skip(1) {
        distance = point_line_distance(&points[i], &points[0], &*points.last().unwrap());
        if distance > dmax {
            index = i;
            dmax = distance;
        }
    }
    if dmax > *epsilon {
        let mut intermediate = rdp(&points[..index + 1], &*epsilon);
        intermediate.pop();
        intermediate.extend_from_slice(&rdp(&points[index..], &*epsilon));
        intermediate
    } else {
        vec![*points.first().unwrap(), *points.last().unwrap()]
    }
}

#[cfg(test)]
mod test {
    use super::{Point};
    use super::{rdp};
        #[test]
    fn rdp_test() {
        let mut vec = Vec::new();
        vec.push(Point::new(0.0, 0.0));
        vec.push(Point::new(5.0, 4.0));
        vec.push(Point::new(11.0, 5.5));
        vec.push(Point::new(17.3, 3.2));
        vec.push(Point::new(27.8, 0.1));
        let mut compare = Vec::new();
        compare.push(Point::new(0.0, 0.0));
        compare.push(Point::new(5.0, 4.0));
        compare.push(Point::new(11.0, 5.5));
        compare.push(Point::new(27.8, 0.1));
        let simplified = rdp(&vec, &1.0);
        assert_eq!(simplified, compare);
    }
}

我已经 impl d SendSync对于 Point<T> , 但当我切换到 par_iter ,我收到以下错误:

error[E0277]: the trait bound rayon::par_iter::skip::Skip<rayon::par_iter::take::Take<rayon::par_iter::enumerate::Enumerate<rayon::par_iter::slice::SliceIter<'_, Point<T>>>>>: std::iter::Iterator is not satisfied
   --> lib.rs:107:5

= note: rayon::par_iter::skip::Skip<rayon::par_iter::take::Take<rayon::par_iter::enumerate::Enumerate<rayon::par_iter::slice::SliceIter<'_, Point<T>>>>> is not an iterator; maybe try calling .iter() or a similar method
= note: required by std::iter::IntoIterator::into_iter

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

最佳答案

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

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

特别是,代码的失败部分似乎是在执行 max_by_key功能。

关于rust - 如何满足 Iterator trait bound 以便在这里使用 Rayon?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42721458/

相关文章:

rust - 使用静态函数实现特征对特征

rust - 如何设置现有结构的值?

rust - ~/.rustup 和 ~/.cargo 中的二进制文件有什么区别?

rust - 如何更改功能以与Rayon并行运行?

multithreading - 如何更改 Rayon 使用的线程数?

rust - Rayon 如何防止在线程之间使用 RefCell<T>、Cell<T> 和 Rc<T>?

rust - Mutex 怎么可能在编译时构造?

rust - 是否可以使用类型注释进行解构赋值?

multithreading - Rayon 中的每线程初始化

linux - Rust `std::time::Instant` "panicked at ' 提供的瞬间晚于 self “