【问题标题】:executable exits early when using io.WriteString使用 io.WriteString 时可执行文件提前退出
【发布时间】:2021-10-22 15:41:51
【问题描述】:

我正在使用 io 包来处理在我的 PATH 中定义的可执行文件。 该可执行文件称为“Stockfish”(国际象棋引擎),显然可以通过命令行工具使用。

为了让引擎搜索最佳移动,您使用“go depth n” - 深度越高 - 搜索所需的时间越长。 使用我的命令行工具,它使用 20 的深度搜索大约 5 秒,它看起来像这样:

go depth 20 info string NNUE evaluation using nn-3475407dc199.nnue enabled info depth 1 seldepth 1 multipv 1 score cp -161 nodes 26 nps 3714 tbhits 0 time 7 pv e7e6 info depth 2 seldepth 2 multipv 1 score cp -161 nodes 51 nps 6375 tbhits 0 time 8 pv e7e6 f1d3 info depth 3 seldepth 3 multipv 1 score cp -161 nodes 79 nps 7900 tbhits 0 time 10 pv e7e6 f1d3 g8f6 info depth 4 seldepth 4 multipv 1 score cp -161 nodes 113 nps 9416 tbhits 0 time 12 pv e7e6 f1d3 g8f6 b1c3 [...] bestmove e7e6 ponder h2h4

现在,使用 io.WriteString 它在几毫秒后完成,无需任何(可见)计算: (这也是下面代码的输出)

Stockfish 14 by the Stockfish developers (see AUTHORS file) info string NNUE evaluation using nn-3475407dc199.nnue enabled bestmove b6b5

这是我使用的代码:

func useStockfish(commands []string) string {
    cmd := exec.Command("stockfish")
    stdin, err := cmd.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }
    for _, cmd := range commands {
        writeString(cmd, stdin)
    }
    err = stdin.Close()
    if err != nil {
        log.Fatal(err)
    }
    out, err := cmd.CombinedOutput()
    if err != nil {
        log.Fatal(err)
    }
    return string(out)
}

func writeString(cmd string, stdin io.WriteCloser) {
    _, err := io.WriteString(stdin, cmd)
    if err != nil {
        log.Fatal(err)
    }

这是我如何使用它的一个例子。第一个命令是设置位置,第二个是计算下一个最好的移动,深度为 20。结果如上所示。

func FetchComputerMove(game *internal.Game) {
    useStockfish([]string{"position exmaplepos\n", "go depth 20"})
}

【问题讨论】:

    标签: go stockfish


    【解决方案1】:

    要利用像 stockfish 这样的引擎 - 您需要启动进程并保持它运行。

    您正在执行它,通过标准输入管道传递 2 个命令,然后关闭管道。关闭管道向程序表明您不再对引擎所说的内容感兴趣。

    要运行它 - 并保持它运行 - 你需要这样的东西:

    func startEngine(enginePath string) (stdin io.WriteCloser, stdout io.ReadCloser, err error) {
        cmd := exec.Command(enginePath )
    
        stdin, err = cmd.StdinPipe()
        if err != nil {
            return
        }
        stdout, err = cmd.StdoutPipe()
        if err != nil {
            return
        }
    
        err = cmd.Start() // start command - but don't wait for it to complete
        return
    }
    

    返回的管道允许您发送命令并实时查看输出:

    stdin, stdout, err := startEngine("/usr/local/bin/stockfish")
    
    
    sendCmd := func(cmd string) error {
        _, err := stdin.Write([]byte(cmd + "\n"))
        return err
    }
    
    sendCmd("position examplepos")
    sendCmd("go depth 20")
    

    然后粗略读取异步响应:

    b := make([]byte, 10240)
    
    for {
        n, err := stdout.Read(b)
        if err != nil {
            log.Fatalf("read error: %v", err)
        }
        log.Println(string(b[:n]))
    }
    

    一旦出现bestmove d2d4 ponder g8f6 这样的行,就知道当前的分析命令已经完成。

    然后,您可以关闭引擎(通过关闭stdin 管道)(如果您只需要这样做),或者将其保持打开状态以供进一步的命令提交。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-26
      • 1970-01-01
      • 2017-05-31
      • 1970-01-01
      • 2017-10-12
      相关资源
      最近更新 更多