我尝试使用Rayon启动一系列顶级线程来递归调用模拟函数。该代码适用于使用频道发送&接收,因此它与多线程兼容,但无法使用par_iter()
进行编译。
fn simulate(initial_board: &Board, player: Player, level: u32, start: bool) -> Option<AMove> {
...
#[inline(always)]
fn evaluate_move(previous: Option<AMove>, new_move: &AMove, new_score: i32, player: Player) -> AMove {
...
}
...
let accumlator = |previous: Option<AMove>, a_move: &Option<AMove>| if let Some(AMove { board: ref a_board, .. }) = *a_move {
...
} else {
previous
};
if start && !winning {
the_move = moves.par_iter().fold(the_move, accumlator);
} else {
the_move = moves.iter().fold(the_move, accumlator);
}
the_move
}
我在使用par_iter()的行上遇到了编译器错误,我对如何解决这些问题感到很遗憾。
error[E0277]: the trait bound `std::option::Option<AMove>: std::ops::Fn<()>` is not satisfied
--> src/main.rs:271:37
|
271 | the_move = moves.par_iter().fold(the_move, accumlator);
| ^^^^ the trait `std::ops::Fn<()>` is not implemented for `std::option::Option<AMove>`
error[E0277]: the trait bound `std::option::Option<AMove>: std::ops::FnOnce<()>` is not satisfied
--> src/main.rs:271:37
|
271 | the_move = moves.par_iter().fold(the_move, accumlator);
| ^^^^ the trait `std::ops::FnOnce<()>` is not implemented for `std::option::Option<AMove>`
error[E0308]: mismatched types
--> src/main.rs:271:20
|
271 | the_move = moves.par_iter().fold(the_move, accumlator);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `rayon::iter::Fold`
|
= note: expected type `std::option::Option<_>`
found type `rayon::iter::Fold<rayon::slice::Iter<'_, std::option::Option<AMove>>, std::option::Option<_>, [closure@src/main.rs:224:22: 240:6 winning:_, level:_, player:_]>`
答案 0 :(得分:2)
Rayon的fold
想要一个产生一个身份元素的函数,而不是一个基本元素。在您的情况下,如果AMove
为Copy + Send + Sync
,则只需执行moves.par_iter().fold(|| the_move, accumlator)
即可。
如果AMove
不是Copy
,请使用|| the_move.clone()
。
Rayon可能希望生成多个标识元素以并行执行不同的块,并且只在最后合并结果,这就是为什么它需要能够生成所需数量的标识元素。
检查fold
&#39; s signature。此外,如果您的累加器返回与identity元素相同的类型,您可能希望使用reduce
代替(请参阅链接文档以了解差异)。
另一个问题是,您不能按照您尝试的方式使用递归闭包(Rust不能这样做)。使用命名函数代替累加器。
答案 1 :(得分:0)
解决方案在于在生成的reduce
上使用fold
。谢谢你暗示我。我终于在Rayon演示中找到了一个例子,为我的案例铺平了解决方案。以下是未来参考的方式。
moves.par_iter()
.fold(|| None, accumlator)
.reduce(|| None, |previous: Option<AMove>, a_move: Option<AMove>| {
if let Some(a_move) = a_move {
Some(select_move(&previous, &a_move, player))
} else {
previous
}
})
最令人费解的错误是最初出现的错误,因为我使用的是fold(a,b)
而不是fold(|| a,b)
,它抱怨Fn
和FnOnce
并让我无能为力。< / p>