Rust -使用线程迭代vector



我的程序创建了一个数字网格,然后根据网格上每个数字周围数字的总和,数字将以一种固定的方式变化。我目前使用两个向量,用随机数填充第一个向量,计算变化,然后将新值放入第二个向量。在新值进入第二个向量后,在进行下一个循环之前,我将它们推回到第一个向量中。我目前得到的错误是:

error[E0499]: cannot borrow `grid_a` as mutable more than once at a time
--> srcmain.rs:40:29
|
38 |               thread::scope(|s| {
|                              - has type `&crossbeam::thread::Scope<'1>`
39 |                   for j in 0..grid_b.len() {
40 |                       s.spawn(|_| {
|                       -       ^^^ `grid_a` was mutably borrowed here in the previous iteration of the loop
|  _____________________|
| |
41 | |                         grid_a[j] = grid_b[j];
| |                         ------ borrows occur due to use of `grid_a` in closure
42 | |                     });
| |______________________- argument requires that `grid_a` is borrowed for `'1`

我当前的代码如下。在尝试学习Rust的过程中,我对c++和c#更熟悉了。如果我删除线程,一切都会编译并正常运行。我不明白如何避免多重借。理想情况下,我想使用一个单独的线程::scope on,并在现有线程::scope之上使用for循环。

use crossbeam::thread;
use rand::Rng;
use std::sync::{Arc, Mutex};
use std::thread::sleep;
use std::time::Duration;
use std::time::Instant;
static NUMROWS: i32 = 4;
static NUMCOLUMNS: i32 = 7;
static GRIDSIZE: i32 = NUMROWS * NUMCOLUMNS;
static PLUSNC: i32 = NUMCOLUMNS + 1;
static MINUSNC: i32 = NUMCOLUMNS - 1;
static NUMLOOP: i32 = 7;
static HIGH: u32 = 35;
fn main() {
let start = Instant::now();
let length = usize::try_from(GRIDSIZE).unwrap();
let total_checks = Arc::new(Mutex::new(0));
let mut grid_a = Vec::<u32>::with_capacity(length);
let mut grid_b = Vec::<u32>::with_capacity(length);
grid_a = fill_grid();
for h in 1..=NUMLOOP {
println!("-- {} --", h);
print_grid(&grid_a);
if h != NUMLOOP {
for i in 0..grid_a.len() {
let mut total_checks = total_checks.lock().unwrap();
grid_b[i] = checker(&grid_a, i.try_into().unwrap());
*total_checks += 1;
}
grid_a.clear();
thread::scope(|s| {
for j in 0..grid_b.len() {
s.spawn(|_| {
grid_a[j] = grid_b[j];
});
}
})
.unwrap();
grid_b.clear();
}
}

当你通过索引访问一个向量(或任何切片)时,你是在借用整个向量。你可以使用迭代器,它可以并行地为你提供对所有项的可变引用。

use crossbeam::thread;
static NUMROWS: i32 = 4;
static NUMCOLUMNS: i32 = 7;
static GRIDSIZE: i32 = NUMROWS * NUMCOLUMNS;
static NUMLOOP: i32 = 7;
fn fill_grid() -> Vec<u32> {
(0..GRIDSIZE as u32).into_iter().collect()
}
fn main() {
let length = usize::try_from(GRIDSIZE).unwrap();
// just do this since else we create a vec and throw it away immediately
let mut grid_a = fill_grid();
let mut grid_b = Vec::<u32>::with_capacity(length);
for h in 1..=NUMLOOP {
println!("-- {} --", h);
println!("{grid_a:?}");
if h != NUMLOOP {
// removed a bunch of unrelated code
for i in 0..grid_a.len() {
grid_b.push(grid_a[i]);
}
// since we overwrite grid_a anyways we don't need to clear it.
// it would give us headaches anyways since grid_a[j] on an empty
// Vec panics.
// grid_a.clear();
thread::scope(|s| {
// instead of accessing the element via index we iterate over
// mutable references so we don't have to borrow the whole
// vector inside the thread
for (pa, b) in grid_a.iter_mut().zip(grid_b.iter().copied()) {
s.spawn(move |_| {
*pa = b + 1;
});
}
})
.unwrap();
grid_b.clear();
}
}
} // add missing }

最新更新