0

我尝试处理具有多个工作线程的数组,就像 Rayon 的par_iter()函数一样,但我想要一个可变引用target,每个线程一个。

我有一个像这样的简单功能


pub fn parallel_map_vector<A:Sync,T:Send,B:Send>(a:&[A], t:&mut [T], b:&mut [B], f:impl Fn(&A,&mut T)+Send+Sync){
    assert_eq!(a.len(),b.len());
    let atomic_counter = AtomicUsize::new(0);
    crossbeam::scope(|scope| {
        for target in t {
            scope.spawn( |_| {
                loop {
                    let idx = atomic_counter.fetch_add(1, Ordering::Relaxed);
                    if idx < a.len() {unsafe{std::slice::from_raw_parts_mut(b,b_len)};
                        f(&a[idx], target)
                    }else{
                        break
                    }
                }
            });
        }
    }).unwrap();
}

出于某种原因,我不断收到错误

error[E0373]: closure may outlive the current function, but it borrows `target`, which is owned by the current function
  --> htm/src/parallel.rs:11:26
   |
9  |     crossbeam::scope(|scope| {
   |                       ----- has type `&crossbeam::thread::Scope<'1>`
10 |         for target in t {
11 |             scope.spawn( |_| {
   |                          ^^^ may outlive borrowed value `target`
...
17 |                         f(&a[idx], target)
   |                                    ------ `target` is borrowed here
   |
note: function requires argument type to outlive `'1`
  --> htm/src/parallel.rs:11:13
   |
11 | /             scope.spawn( |_| {
12 | |                 loop {
13 | |                     let idx = atomic_counter.fetch_add(1, Ordering::Relaxed);
14 | |                     if idx < a.len() {
...  |
21 | |                 }
22 | |             });
   | |______________^
help: to force the closure to take ownership of `target` (and any other referenced variables), use the `move` keyword
   |
11 |             scope.spawn( move |_| {

但是当我在 rust 操场上尝试它时,它编译没有问题 https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a10cbfd2f135975f4682c843664d539 这里有什么问题?代码对我来说看起来很安全。

4

1 回答 1

2

您链接到的操场示例是使用 2021 版的 Rust,它允许在闭包中进行不相交的捕获(因此每个线程的闭包仅捕获target而不是整个t切片)。如果您切换到 2018 edition,它会产生与您的问题相同的错误。

Cargo.toml在您的(需要 rustc >= 1.56.0)中指定您需要 2021 版。

于 2022-01-31T11:23:37.490 回答