如何使用带有泛型向量的人造丝的.par_iter()?

dav*_*eil 5 generics rust rayon

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

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));
}
Run Code Online (Sandbox Code Playgroud)

编译时出现这种错误,"方法par_iter存在,但不满足以下特征限制:&std::vec::Vec<T> : rayon::par_iter::IntoParallelIterator".如果我使用iter代替par_iter或如果我切换到使用f32f64代替通用,代码工作正常.

我能做些什么才能par_iter在泛型载体上使用?该IntoParallelIterator特征是否意味着由最终用户实施?我该怎么做呢?

She*_*ter 7

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

查看以下的实施者IntoParallelIterator:

impl<'data, T: Sync + 'data> IntoParallelIterator for &'data [T]
Run Code Online (Sandbox Code Playgroud)

添加问题的Sync绑定修复.Rayon可能会使用多个线程,但是你的原始版本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`
Run Code Online (Sandbox Code Playgroud)

退房collect:

fn collect<C>(self) -> C 
    where C: FromParallelIterator<Self::Item>
Run Code Online (Sandbox Code Playgroud)

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

impl<T> FromParallelIterator<T> for Vec<T> where T: Send
Run Code Online (Sandbox Code Playgroud)

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

fn sqrts<T: Float + Send + Sync>(floats: &[T]) -> Vec<T>
Run Code Online (Sandbox Code Playgroud)

  • 在发送线程时,"发送"和"同步"都会出现很多!这里的逻辑应该很简单.`par_iter`意味着将`&T`分配给不同的线程.这意味着`T:Sync`.Map按值返回`T`s(并将它们传递给潜在的新线程),需要`T:Send`.`collect`需要`T:Send`同样的方式.人造丝可以通过预先收紧特征来帮助:https://github.com/nikomatsakis/rayon/issues/204 (2认同)