不能使用 Rayon 的 `.par_iter()`
Cannot use Rayon's `.par_iter()`
我有一个实现 Iterator
的结构,它作为迭代器工作正常。它生成值,并使用 .map()
,我从本地 HTTP 服务器下载每个项目并保存结果。我现在想并行化这个操作,Rayon 看起来很友好。
我在尝试按照文档中的示例操作时遇到编译器错误。
这是按顺序工作的代码。 generate_values
returns 实现 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 和人造丝 0.3.1
$ rustc --version
rustc 1.6.0 (c30b771ad 2016-01-19)
不,Iterator
特性与 iter()
方法无关。是的,这有点令人困惑。
这里有几个不同的概念。一个Iterator
是可以吐值的类型;它只需要实现 next()
并且还有许多其他方法,但是其中 none 是 iter()
。然后是 IntoIterator
表示类型可以转换为 Iterator
。此特征具有 into_iter()
方法。现在 iter()
方法与这两个特征中的任何一个都不 真正 相关。它只是许多类型的普通方法,通常类似于 into_iter()
.
现在解决你的 Rayon 问题:看起来你不能只使用任何普通迭代器并将其变成并行迭代器。但是,我从未使用过这个库,所以对此持保留态度。在我看来,您需要将迭代器收集到 Vec
中才能使用 par_iter()
.
注意:使用普通迭代器时,不应使用 map()
和 count()
,而应使用标准 for
循环。
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()
}
}
这就是为什么 到 collect
到 Vec
会起作用的原因; Vec
取消对切片的引用。
通常,Rayon 无法假定 any 迭代器可以并行化,因此它不能默认包含所有 Iterator
。
既然你已经定义了 generate_values
,你也可以为它实现适当的 Rayon 特性:
IntoParallelIterator
IntoParallelRefIterator
IntoParallelRefMutIterator
这应该可以让您避免收集到临时向量中。
我有一个实现 Iterator
的结构,它作为迭代器工作正常。它生成值,并使用 .map()
,我从本地 HTTP 服务器下载每个项目并保存结果。我现在想并行化这个操作,Rayon 看起来很友好。
我在尝试按照文档中的示例操作时遇到编译器错误。
这是按顺序工作的代码。 generate_values
returns 实现 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 和人造丝 0.3.1
$ rustc --version
rustc 1.6.0 (c30b771ad 2016-01-19)
不,Iterator
特性与 iter()
方法无关。是的,这有点令人困惑。
这里有几个不同的概念。一个Iterator
是可以吐值的类型;它只需要实现 next()
并且还有许多其他方法,但是其中 none 是 iter()
。然后是 IntoIterator
表示类型可以转换为 Iterator
。此特征具有 into_iter()
方法。现在 iter()
方法与这两个特征中的任何一个都不 真正 相关。它只是许多类型的普通方法,通常类似于 into_iter()
.
现在解决你的 Rayon 问题:看起来你不能只使用任何普通迭代器并将其变成并行迭代器。但是,我从未使用过这个库,所以对此持保留态度。在我看来,您需要将迭代器收集到 Vec
中才能使用 par_iter()
.
注意:使用普通迭代器时,不应使用 map()
和 count()
,而应使用标准 for
循环。
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()
}
}
这就是为什么 collect
到 Vec
会起作用的原因; Vec
取消对切片的引用。
通常,Rayon 无法假定 any 迭代器可以并行化,因此它不能默认包含所有 Iterator
。
既然你已经定义了 generate_values
,你也可以为它实现适当的 Rayon 特性:
IntoParallelIterator
IntoParallelRefIterator
IntoParallelRefMutIterator
这应该可以让您避免收集到临时向量中。