[英]Error with Rayon, cannot borrow `*self` as mutable, as it is a captured variable in a `Fn` closure
First of all, I'm new toRust.首先,我是 Rust 的新手。 For a game I'm working on I need to call function to change pixels on a vector that is then transformed into an iamge.
对于我正在开发的游戏,我需要调用 function 来更改矢量上的像素,然后将其转换为图像。 For that, I have a struct that contains all the context of the game, include said image and everything I need to calcaulate the pixels.
为此,我有一个包含游戏所有上下文的结构,包括所述图像和计算像素所需的一切。
This works with a single thread but not when I try to parallelize it with Rayon.这适用于单个线程,但当我尝试将其与 Rayon 并行化时则无效。
Here's a simplified code as an example of the problem.这是一个简化的代码作为问题的示例。 It works with
chunks_mut
.它适用于
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();
}
Error错误
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 uses the &mut self
receiver. Your
Game::some_function
function 使用&mut self
接收器。 This means that it must borrow self
mutably.这意味着它必须可变地借用
self
。 That is, self.some_function(slice)
is the same as Game::some_function(&mut self, slice)
.也就是说,
self.some_function(slice)
与Game::some_function(&mut self, slice)
相同。
So when you call self.some_function(slice)
in your closure, the closure must capture self
as mutable, since it needs to borrow self
as mutable to call the function. However, the for_each
function requires a Fn
closure and a Fn
closure will not let you capture as mutable (for good reason).因此,当您在闭包中调用
self.some_function(slice)
时,闭包必须将self
捕获为可变的,因为它需要借用self
作为可变的来调用 function。但是, for_each
function 需要Fn
闭包,而Fn
闭包不会让您捕获为可变的(有充分的理由)。
The solution in your case is to change the receiver in some_function
to &self
, since as written that function doesn't need mutable access to self
:您的解决方案是将
some_function
中的接收器更改为&self
,因为正如所写的那样 function 不需要对self
进行可变访问:
fn some_function(&self, slice: &mut [u8]) {
// ...
}
Edit:编辑:
To complete the explanation: the rayon par_chunks_mut
method returns a type that implements ParallelIterator
, which is where the for_each
method comes from.完成解释:人造丝
par_chunks_mut
方法返回一个实现ParallelIterator
的类型,这是for_each
方法的来源。 That's where the argument implementing Fn
is required.这就是需要参数实现
Fn
的地方。
Now thinking about the available closure traits in Rust, why Fn
?现在想想 Rust 中可用的闭包特征,为什么是
Fn
? Well the other options are FnOnce
or FnMut
.那么其他选项是
FnOnce
或FnMut
。 FnOnce
consumes the closure when called once and thus can only be called at most once (hence the name), clearly this isn't going to work for a for_each
method. FnOnce
在调用一次时消耗闭包,因此最多只能调用一次(因此得名),显然这不适用于for_each
方法。 FnMut
is weaker, it can capture variables mutably, so why does rayon not use that? FnMut
较弱,它可以可变地捕获变量,那么为什么 rayon 不用它呢? The entire point is to call this closure concurrently in different threads, which you can't do if you're mutating its state, you'd have to synchronise the mutable access which would effectively serialise the operation, making the whole thing a waste of time.重点是在不同的线程中同时调用这个闭包,如果你改变它的 state,你就不能这样做,你必须同步可变访问,这将有效地序列化操作,使整个事情成为浪费时间。 Thus,
Fn
is the only option and no mutable captures are allowed.因此,
Fn
是唯一的选择,不允许进行可变捕获。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.