繁体   English   中英

Rayon 出错,不能借用 `*self` 作为可变的,因为它是 `Fn` 闭包中的捕获变量

[英]Error with Rayon, cannot borrow `*self` as mutable, as it is a captured variable in a `Fn` closure

首先,我是 Rust 的新手。 对于我正在开发的游戏,我需要调用 function 来更改矢量上的像素,然后将其转换为图像。 为此,我有一个包含游戏所有上下文的结构,包括所述图像和计算像素所需的一切。

这适用于单个线程,但当我尝试将其与 Rayon 并行化时则无效。

这是一个简化的代码作为问题的示例。 它适用于chunks_mut

use ::rayon::prelude::*;
struct Game {
    pub pixel: [u8; 4],
    pub pixel_vec: Vec<u8>,
}

impl Game {
    pub fn new(pixel: [u8; 4], length: usize) -> Self {
        let pixel_vec = vec![2; length];

        Self { pixel, pixel_vec }
    }
    pub fn draw(&mut self) {
        let mut pixel_vec = std::mem::take(&mut self.pixel_vec);

        pixel_vec
            .par_chunks_mut(4)
            .for_each(|slice| self.some_function(slice));
        self.pixel_vec = pixel_vec;
    }

    fn some_function(&mut self, slice: &mut [u8]) {
        for i in 0..slice.len() {
            slice[i] = self.pixel[i] * self.pixel[i];
        }
    }
}

fn main() {
    let mut game = Game::new([0, 3, 0, 0], 20);
    game.draw();
}

错误

Compiling playground v0.0.1 (/playground)
error[E0596]: cannot borrow `*self` as mutable, as it is a captured variable in a `Fn` closure
  --> src/main.rs:18:31
   |
18 |             .for_each(|slice| self.some_function(slice));
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

For more information about this error, try `rustc --explain E0596`.
error: could not compile `playground` due to previous error

Your Game::some_function function 使用&mut self接收器。 这意味着它必须可变地借用self 也就是说, self.some_function(slice)Game::some_function(&mut self, slice)相同。

因此,当您在闭包中调用self.some_function(slice)时,闭包必须将self捕获为可变的,因为它需要借用self作为可变的来调用 function。但是, for_each function 需要Fn闭包,而Fn闭包不会让您捕获为可变的(有充分的理由)。

您的解决方案是将some_function中的接收器更改为&self ,因为正如所写的那样 function 不需要对self进行可变访问:

fn some_function(&self, slice: &mut [u8]) {
    // ...
}

编辑:

完成解释:人造丝par_chunks_mut方法返回一个实现ParallelIterator的类型,这是for_each方法的来源。 这就是需要参数实现Fn的地方。

现在想想 Rust 中可用的闭包特征,为什么是Fn 那么其他选项是FnOnceFnMut FnOnce在调用一次时消耗闭包,因此最多只能调用一次(因此得名),显然这不适用于for_each方法。 FnMut较弱,它可以可变地捕获变量,那么为什么 rayon 不用它呢? 重点是在不同的线程中同时调用这个闭包,如果你改变它的 state,你就不能这样做,你必须同步可变访问,这将有效地序列化操作,使整个事情成为浪费时间。 因此, Fn是唯一的选择,不允许进行可变捕获。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM