我有一个实现Iterator
的结构,它作为迭代器工作正常。它生成值,并使用.map()
,从本地HTTP服务器下载每个项目并保存结果。我现在想要并行化此操作,Rayon看起来很友好。
尝试按照文档中的示例进行编译时出错。
这是按顺序工作的代码。 generate_values
返回实现Iterator
的结构。 dl
下载值并保存它们(即它有副作用)。由于迭代器在Rust中是懒惰的,所以我在最后添加了一个.count()
,以便它实际运行它。
generate_values(14).map(|x| { dl(x, &path, &upstream_url); }).count();
按照人造丝的例子,我尝试了这个:
generate_values(14).par_iter().map(|x| { dl(x, &path, &upstream_url); }).count();
并收到以下错误:
src/main.rs:69:27: 69:37 error: no method named `par_iter` found for type `MyIterator` in the current scope
有趣的是,当我使用许多Rust使用的.iter()
时,我得到了类似的错误:
src/main.rs:69:27: 69:33 error: no method named `iter` found for type `MyIterator` in the current scope
src/main.rs:69 generate_values(14).iter().map(|tile| { dl_tile(tile, &tc_path, &upstream_url); }).count();
自从我实施Iterator
以来,我应该免费获得.iter()
吗?这是.par_iter()
不起作用的原因吗?
Rust 1.6和Rayon 0.3.1
$ rustc --version
rustc 1.6.0 (c30b771ad 2016-01-19)
答案 0 :(得分:5)
Rayon 0.3.1将par_iter
定义为:
pub trait IntoParallelRefIterator<'data> {
type Iter: ParallelIterator<Item=&'data Self::Item>;
type Item: Sync + 'data;
fn par_iter(&'data self) -> Self::Iter;
}
只有one type that implements this trait in Rayon itself: [T]
:
impl<'data, T: Sync + 'data> IntoParallelRefIterator<'data> for [T] {
type Item = T;
type Iter = SliceIter<'data, T>;
fn par_iter(&'data self) -> Self::Iter {
self.into_par_iter()
}
}
这就是Lukas Kalbertodt's answer到collect
到Vec
的原因; Vec
取消引用切片。
通常,Rayon不能假设任何迭代器都适合并行化,因此它不能默认包含所有Iterator
。
由于你已经定义了generate_values
,你也可以为它实现适当的人造丝特性:
IntoParallelIterator
IntoParallelRefIterator
IntoParallelRefMutIterator
这应该可以避免收集临时载体。
答案 1 :(得分:4)
不,Iterator
特征与iter()
方法无关。是的,这有点令人困惑。
这里有一些不同的概念。 Iterator
是一种可以吐出值的类型;它只需要实现next()
并有许多其他方法,但这些方法都不是iter()
。然后有IntoIterator
表示类型可以转换为Iterator
。此特征具有into_iter()
方法。现在,iter()
方法确实 与这两个特征中的任何一个都无关。它只是许多类型的常规方法,通常与into_iter()
类似。
现在你的Rayon问题:看起来你不能只采用任何正常的迭代器并将它变成一个平行的迭代器。但是,我从来没有使用过这个库,因此需要花一点时间。对我而言,您似乎需要将迭代器收集到Vec
中才能使用par_iter()
。
正如注意:使用普通迭代器时,不应使用map()
和count()
,而应使用标准for
循环。