如何在国际象棋搜索算法中使用Python多处理库?

问题描述 投票:0回答:1

我目前正在开发一个国际象棋引擎,我正在将并行化视为一种优化搜索合法走法以找到最佳走法所需时间的方法。我找到了Python模块multiprocessing,但是由于它需要在“main”==“name”中执行,我将如何在当前的类模型中使用它?我的代码看起来像这样:

class ourEngine:
    def __init__(self, board, engine_color, thinking_time=0):
        self.board = board
        self.thinking_time = thinking_time
        self.engine_color = engine_color

    def evaluate(self, board):
        # Evaluation calculation
    
    def search(self, board, depth, engine_color, alpha=float("-inf"), beta=float("inf")):
        # Minimax algorithm with alpha-beta pruning for every move in python-chess board.legal_moves

如何在没有 init 的情况下实现多处理库中的池以在所有 GPU 上同时处理 legal_moves?我还意识到我必须设置一个队列,但我在任何地方都找不到在线示例

我尝试在一个单独的函数中实现该模块,然后调用搜索,但它不起作用。

python multiprocessing chess python-chess
1个回答
0
投票

在使用 spawn 方法创建子进程的平台(例如 Windows)上,要启动子进程,Python 会在新进程的地址空间中启动一个新的 Python 解释器,该解释器重新处理在全局范围内执行所有内容的源代码(导入语句、全局变量、函数定义、类定义等)来初始化内存,然后才执行您指定在新进程中最初执行的函数/方法。

此方案的问题在于,全局范围内直接创建子进程或间接创建子进程的任何语句(例如,通过调用最终创建子进程的函数)都会导致递归子进程创建循环(这不会这实际上不会发生,因为 Python 检测到在此内存初始化阶段创建新子进程的尝试)。

为了解决这个问题,任何此类直接或间接的进程创建语句都必须放置在

if __name__ == '__main__':
块中。递归将被阻止,因为
__name__
在任何子进程中都不会是
'__main__'
,因此不会执行进程创建语句。

想象一下,您修改了

search
方法,以便它创建子进程,并在其中分配搜索。因此,最终调用此方法的全局范围内的任何代码都需要位于该特殊的
if
块中。例如:

class OurEngine:
    ... # Code omitted for brevity

def create_engine_and_search():
    ... # Code omitted
    engine = OurEngine(board, some_color, some_thinking_time_
    ...
    engine.search()

def main():
    ...
    create_engine_and_search()

# Invoice main:
main()

main
的调用是在全局范围内的。由于调用
main
,最终将调用
OurEngine.search
,我们假设
search
方法创建子进程。为了初始化这些新进程的内存,该文件将在新进程中重新解释,并且全局范围内的
main
将被再次调用。这是个问题!但我们需要做的是:

...

# Only call main if we are the main process:
if __name__ == '__main__':
    main()

您的平台是什么?我们必须使用当前平台标记所有多处理问题,因为答案取决于平台。例如,如果您在 Linux 下运行,则会使用不同的机制来初始化新子进程的内存,我们不需要特殊的

if
测试。

© www.soinside.com 2019 - 2024. All rights reserved.