下面有一个玩具示例,其中我对一个简单的结构向量进行迭代并对其进行并行操作。并行操作后,我想将所有结果加载到稀疏矩阵中。
extern crate rayon;
extern crate sprs;
use rayon::prelude::*;
use sprs::TriMat;
pub struct Data {
i: usize,
}
fn eval<'a>(d: &Data) -> usize {
d.i * 2
}
fn main() {
let data = vec![1, 2, 3, 4];
let mut recs = Vec::new();
for x in data {
let s = Data { i: x };
recs.push(s);
}
let results = recs.par_iter().map(eval);
let mut matrix = TriMat::new((4, 2));
results.enumerate().for_each(|(j, scores)| {
matrix.add_triplet(j, j as usize, 1);
});
}
代码导致错误:
error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
--> src/main.rs:26:9
|
26 | matrix.add_triplet(j, j as usize, 1);
| ^^^^^^
|
help: consider changing this closure to take self by mutable reference
--> src/main.rs:25:34
|
25 | results.enumerate().for_each(|(j, scores)| {
| __________________________________^
26 | | matrix.add_triplet(j, j as usize, 1);
27 | | });
| |_____^
我不明白如何可变地借用数据。
答案 0 :(得分:1)
这是因为map
实际上并没有做任何事情。它创建了一个尚待迭代的新迭代器。
一旦我们碰到了matrix.add_triplet(j, j as usize, 1);
代码,该迭代器就会被迭代,但是它是ParallelIterator
...因此,Rust编译器现在担心数据争用。
您有两种选择。
首先,您可以立即强制评估迭代器。.
let results: Vec<_> = recs.par_iter().map(eval).collect();
// ...
results.iter().enumerate() // ...
或者您可以将对矩阵的访问权包装在Mutex
(或其他同步机制)中:
use std::sync::Mutex;
// ...
let mut matrix = Mutex::new(TriMat::new((4, 2)));
// ...
matrix.lock().unwrap().add_triplet(j, j as usize, 1);
什么是最适合您的呢?鉴于您与我们分享了一些小样本,我不能完全确定,但希望可以让您了解正在发生的事情。