首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Error with Rayon,不能将`*self`‘作为可变的,因为它是’in‘闭包中捕获的变量

Error with Rayon,不能将`*self`‘作为可变的,因为它是’in‘闭包中捕获的变量
EN

Stack Overflow用户
提问于 2022-03-23 11:05:22
回答 1查看 399关注 0票数 0

首先,我是新toRust。对于我正在进行的游戏,我需要调用函数来改变向量上的像素,然后将其转换为iamge。为此,我有一个结构,它包含游戏的所有上下文,包括所述图像以及计算像素所需的一切。

这只适用于一个线程,但当我试图将它与人造丝并行时,它就不行了。

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

代码语言:javascript
复制
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();
}

错误

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2022-03-23 23:02:24

您的Game::some_function函数使用&mut self接收器。这意味着它必须不断借用self。也就是说,self.some_function(slice)Game::some_function(&mut self, slice)是一样的。

因此,当您在闭包中调用self.some_function(slice)时,闭包必须将self捕获为可变的,因为它需要以可变的self来调用函数。但是,for_each函数需要一个Fn闭包,并且Fn闭包不会让您捕获为可变的(出于很好的理由)。

在您的情况下,解决方案是将some_function中的接收方更改为&self,因为编写时该函数不需要对self的可变访问

代码语言:javascript
复制
fn some_function(&self, slice: &mut [u8]) {
    // ...
}

编辑:

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

现在想想铁锈中的有效闭锁性状,为什么是Fn?其他的选择是FnOnceFnMutFnOnce在调用一次时消耗闭包,因此最多只能调用一次(因此名称),显然这对for_each方法不起作用。FnMut比较弱,它可以可变地捕获变量,那么为什么人造丝不使用它呢?关键是要在不同的线程中并发调用这个闭包,如果您改变了它的状态,就必须同步可变的访问,这将有效地序列化操作,使整个过程成为浪费时间。因此,Fn是唯一的选项,不允许任何可变捕获。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71586137

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档