首先,我是新toRust。对于我正在进行的游戏,我需要调用函数来改变向量上的像素,然后将其转换为iamge。为此,我有一个结构,它包含游戏的所有上下文,包括所述图像以及计算像素所需的一切。
这只适用于一个线程,但当我试图将它与人造丝并行时,它就不行了。
下面是一个简化的代码,作为这个问题的一个例子。它适用于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发布于 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的可变访问
fn some_function(&self, slice: &mut [u8]) {
// ...
}编辑:
要完成解释:人造丝par_chunks_mut方法返回实现ParallelIterator的类型,这是for_each方法的来源。这就是实现Fn的参数需要的地方。
现在想想铁锈中的有效闭锁性状,为什么是Fn?其他的选择是FnOnce或FnMut。FnOnce在调用一次时消耗闭包,因此最多只能调用一次(因此名称),显然这对for_each方法不起作用。FnMut比较弱,它可以可变地捕获变量,那么为什么人造丝不使用它呢?关键是要在不同的线程中并发调用这个闭包,如果您改变了它的状态,就必须同步可变的访问,这将有效地序列化操作,使整个过程成为浪费时间。因此,Fn是唯一的选项,不允许任何可变捕获。
https://stackoverflow.com/questions/71586137
复制相似问题