- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个在 Vec<T>
上运行的函数其目的是使用对现有项目的引用生成的新项目来扩展向量。我正在尝试使用 rayon
并行运行新数据的生成.
这是一个最小的例子:
use itertools::Itertools;
use rayon::prelude::*;
fn main() {
let mut foo = Foo {
data: (0..1000).into_iter().collect(),
};
foo.run();
}
struct Foo<T> {
data: Vec<T>,
}
type Pair<'a, T> = (&'a T, &'a T);
impl<'a, T: Clone + 'a> Foo<T>
where
Vec<Pair<'a, T>>: IntoParallelIterator<Item = Pair<'a, T>>,
[T; 2]: IntoParallelIterator,
Vec<T>: FromParallelIterator<<[T; 2] as IntoParallelIterator>::Item>,
{
fn run(&'a mut self) {
let combinations: Vec<Pair<'a, T>> = self
.data
.iter()
.combinations(2)
.map(|x| (x[0], x[1]))
.collect();
let mut new_combinations: Vec<T> = combinations
.into_par_iter()
.flat_map(|(a, b)| bar(a, b))
.collect();
self.data.append(&mut new_combinations);
}
}
fn bar<T: Clone>(a: &T, b: &T) -> [T; 2] {
[a.clone(), b.clone()]
}
您可以找到 Playground 的链接 here .
构建上述示例会引发此错误:
error[E0502]: cannot borrow `self.data` as mutable because it is also borrowed as immutable
--> src/main.rs:36:9
|
17 | impl<'a, T: Clone + 'a> Foo<T>
| -- lifetime `'a` defined here
...
24 | let combinations: Vec<Pair<'a, T>> = self
| ___________________________----------------___-
| | |
| | type annotation requires that `self.data` is borrowed for `'a`
25 | | .data
26 | | .iter()
| |___________________- immutable borrow occurs here
...
36 | self.data.append(&mut new_combinations);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
据我所知,因为我收集到 let new_combinations: Vec<T>
不应该有对 self.data
的不可变引用理论上我应该能够可变地借用它来附加新的组合。但是,似乎 self.data
为'a
借用这超出了此方法的范围。我找不到避免指定生命周期的方法 fn run(&'a mut self)
因为我需要指定对 self.data
项的引用的生命周期活不过self
在创建组合时。
有没有办法让这个方法按预期运行,那就是:1)选择一个引用列表self.data
中的项目。 , 2) 应用创建新项目的函数 T
并行,最后 3) 更新 self.data
与新项目。
请注意,作为一种解决方法,可以返回 new_combinations
从方法并将它们附加到 self.data
分别。
如果所有这些都可以通过避免尽可能多的 collect()
来实现,那就太好了尽可能直接使用迭代器操作。
最佳答案
new_combinations
中的元素是克隆的,因此不再从 combinations
中借用。但是,您的注释声明 T: 'a
,这意味着 Rust 必须将它们视为仍然借用。
我个人认为你对这里的生命周期注释太过分了,你可以删除几乎所有的生命周期注释。在大多数情况下,编译器非常擅长自动找出它们。
此外,可悲的是,您的特征限制被编译器提示误导了。一旦您指定 T: Clone + Send + Sync
,它们都会自动完成。
给你:
use itertools::Itertools;
use rayon::prelude::*;
fn main() {
let mut foo = Foo {
data: (0..10).collect(),
};
foo.run();
println!("{:?}", foo.data);
}
struct Foo<T> {
data: Vec<T>,
}
type Pair<'a, T> = (&'a T, &'a T);
impl<T: Clone + Send + Sync> Foo<T> {
fn run(&mut self) {
let combinations: Vec<Pair<T>> = self
.data
.iter()
.combinations(2)
.map(|x| (x[0], x[1]))
.collect();
let mut new_combinations: Vec<T> = combinations
.into_par_iter()
.flat_map(|(a, b)| bar(a, b))
.collect();
self.data.append(&mut new_combinations);
}
}
fn bar<T: Clone>(a: &T, b: &T) -> [T; 2] {
[a.clone(), b.clone()]
}
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 2, 3, 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9, 3, 4, 3, 5, 3, 6, 3, 7, 3, 8, 3, 9, 4, 5, 4, 6, 4, 7, 4, 8, 4, 9, 5, 6, 5, 7, 5, 8, 5, 9, 6, 7, 6, 8, 6, 9, 7, 8, 7, 9, 8, 9]
此外,确实不需要 Pair
类型:
use itertools::Itertools;
use rayon::prelude::*;
fn main() {
let mut foo = Foo {
data: (0..10).collect(),
};
foo.run();
println!("{:?}", foo.data);
}
struct Foo<T> {
data: Vec<T>,
}
impl<T: Clone + Send + Sync> Foo<T> {
fn run(&mut self) {
let combinations: Vec<_> = self
.data
.iter()
.combinations(2)
.map(|x| (x[0], x[1]))
.collect();
let mut new_combinations: Vec<T> = combinations
.into_par_iter()
.flat_map(|(a, b)| bar(a, b))
.collect();
self.data.append(&mut new_combinations);
}
}
fn bar<T: Clone>(a: &T, b: &T) -> [T; 2] {
[a.clone(), b.clone()]
}
关于你问题的最后一部分,要求尽可能删除所有 .collect()
调用:
遗憾的是,我认为您无法删除任何 collect()
。至少不是您当前的代码布局。您肯定需要在 combinations()
和 into_par_iter()
之间 collect()
,而且您肯定还需要 collect()
在 append
之前,因为您需要在写入之前释放对 self.data
的所有引用。
关于rust - 如何避免使用 IntoParallelIterator 绑定(bind)的可变和不可变借用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73733163/
我有一个在 Vec 上运行的函数其目的是使用对现有项目的引用生成的新项目来扩展向量。我正在尝试使用 rayon 并行运行新数据的生成. 这是一个最小的例子: use itertools::Iterto
我是一名优秀的程序员,十分优秀!