我有一个实现 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
有趣的是,当我使用 .iter()
时,许多 Rust 东西都使用了它,我得到了一个类似的错误:
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.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
,您也可以为它实现适当的 Rayon 特性:
IntoParallelIterator
IntoParallelRefIterator
IntoParallelRefMutIterator
这应该可以让您避免收集到临时向量中。
关于parallel-processing - 不能使用 Rayon 的 `.par_iter()`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35863996/