我在尝试使用Alpha-Beta极小极大搜索算法创建一个国际象棋引擎,但代码运行速度太慢。我已经尽可能地进行了优化,但在单线程下仍然非常慢。我查看了其他引擎的源代码以了解它们是如何实现的,并且查阅了国际象棋编程维基(https://www.chessprogramming.org/Parallel_Search#Parallel_Alpha-Beta),但那些代码超出了我的理解范围,我找不到任何书面资料或代码片段。
有人能解释如何在Alpha-Beta搜索算法中高效地实现多线程吗?谢谢。
回答:
Alpha-Beta算法本质上是一个顺序算法,因为你的Alpha和Beta值在整个搜索过程中不断更新,剪枝决策基于这些值。因此,通过增加线程数量来提高速度是非常困难的,而且线程越多,收益越小。
然而,还是有几种方法可以实现,尽管大多数方法相当复杂,且随着线程数量的增加,扩展性极差。过去常用的算法是Young Brothers等待概念,这是一个相当复杂的算法,例如Stockfish几年前还在使用。然而,随着现代计算机上可用核数的增加,这种方法的扩展性非常差,代码也非常复杂。现在,大多数现代引擎使用的是所谓的Lazy SMP。这种算法几乎是最简单的,并且比其他算法扩展性更好。
在Lazy SMP中,你所要做的就是像平常一样启动搜索,只是使用多个线程。它依赖于一个工作中的转置表,通过该表线程之间进行通信。线程永远不会完全同步,这种随机性会导致每个线程探索搜索树的略有不同的部分,然后将结果保存到转置表中,供其他线程使用。当然,每个线程会重复一些工作,但这仍然比试图聪明地分割工作并减慢算法要好,尤其是在你开始增加线程数量时更是如此。
我建议你查看国际象棋编程维基,你甚至可以找到一些关于如何实现它的伪代码。https://www.chessprogramming.org/Lazy_SMP
不过,我还应该指出,如果你想要的是提高搜索深度的时间,实现多线程并不会帮你太多(在某些极端情况下甚至可能减慢速度!)。你需要的是对搜索树进行更积极的剪枝和更高效的实现(例如,没有内存分配,这样垃圾回收器就永远不需要运行,等等)。