[英]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
? 那么其他选项是FnOnce
或FnMut
。 FnOnce
在调用一次时消耗闭包,因此最多只能调用一次(因此得名),显然这不适用于for_each
方法。 FnMut
较弱,它可以可变地捕获变量,那么为什么 rayon 不用它呢? 重点是在不同的线程中同时调用这个闭包,如果你改变它的 state,你就不能这样做,你必须同步可变访问,这将有效地序列化操作,使整个事情成为浪费时间。 因此, Fn
是唯一的选择,不允许进行可变捕获。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.