7

这是一个人为的例子,但我相信如果我能做到这一点,我可以将它应用到我的具体案例中。

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

fn sqrts<T: Float>(floats: &Vec<T>) -> Vec<T> {
    floats.par_iter().map(|f| f.sqrt()).collect()
}

fn main() {
    let v = vec![1.0, 4.0, 9.0, 16.0, 25.0];
    println!("{:?}", sqrts(&v));
}

此错误在编译时出现“方法par_iter存在但不满足以下特征界限:&std::vec::Vec<T> : rayon::par_iter::IntoParallelIterator”。如果我使用iter代替par_iter或切换到使用f32f64代替泛型,则代码可以正常工作。

我该怎么做才能par_iter在泛型向量上使用?该IntoParallelIterator特征是否打算由最终用户实现?我该怎么做呢?

4

1 回答 1

7

首先,阅读为什么不鼓励接受对字符串 (&String) 或 Vec (&Vec) 的引用作为函数参数?. 然后...

审查以下实现者IntoParallelIterator

impl<'data, T: Sync + 'data> IntoParallelIterator for &'data [T]

添加Sync绑定修复了该问题。人造丝通过可能使用多个线程来工作,但是您的原始T版本不保证共享或线程之间是否安全!这是第二次出现:

error: no method named `collect` found for type `rayon::par_iter::map::Map<rayon::par_iter::slice::SliceIter<'_, T>, rayon::par_iter::map::MapFn<[closure@src/main.rs:7:27: 7:39]>>` in the current scope
 --> src/main.rs:7:41
  |
7 |     floats.par_iter().map(|f| f.sqrt()).collect()
  |                                         ^^^^^^^
  |
  = note: the method `collect` exists but the following trait bounds were not satisfied: `rayon::par_iter::map::MapFn<[closure@src/main.rs:7:27: 7:39]> : rayon::par_iter::map::MapOp<&_>`, `rayon::par_iter::map::Map<rayon::par_iter::slice::SliceIter<'_, T>, rayon::par_iter::map::MapFn<[closure@src/main.rs:7:27: 7:39]>> : std::iter::Iterator`

退房collect

fn collect<C>(self) -> C 
    where C: FromParallelIterator<Self::Item>

我们可以看到目标类型需要实现FromParallelIterator

impl<T> FromParallelIterator<T> for Vec<T> where T: Send

因此,添加两个边界允许它编译:

fn sqrts<T: Float + Send + Sync>(floats: &[T]) -> Vec<T>
于 2017-01-10T19:15:16.607 回答