USIプロトコルでisreadyは毎局必ず送られるのか?

結論的には、将棋所とShogiGUIでは連続対局のときにも毎局送られてきます。
なので、思考エンジンの作者は、毎局、isreadyが送られてくることを期待して書いても問題とはならないはずです。

本来、isreadyは、時間のかかる初期化(評価関数ファイルの読み込み)などを行なうためのもので、基本的には起動後、1回すればいいはずです。isreadyのあと思考エンジン側がreadyokを返すまでは持ち時間が減らないという仕様なので、置換表のクリアもisreadyのときにやっているエンジン作者もいるでしょう。(やねうら王もそうしています。)

しかしUSIの規範となったUCIプロトコルを用いるStockfishのソースコードを見たところ、どうもisreadyは連続対局のときの2局目以降、送られてくるのを期待するコードにはなっていなくて、ucinewgame(将棋のusinewgameに相当する)で置換表のクリアや探索の初期化などをしています。置換表に64GBほど確保するような場合、このクリアだけで数十秒かかると思うのですが、その間、持ち時間が減るので損だと思います。

Stockfishのソースコードの実装がおかしい気はします。私は以前からこの部分を修正してpull requestしようかと思っているのですが、いまひとつ確信が持てないのでやっていません。というのも、UCIプロトコルにおいてisreadyが毎局送られてくることが保証されていないのだとしたら、いまのStockfishのようなコードにするしかないからです。

詳しい人がおられましたら、コメント欄などで教えてください。

USIプロトコルでisreadyは毎局必ず送られるのか?” への8件のコメント

    • リンク先の記事、詳しい人がいるんだなー!と思ったら自分が5年前に書いた記事でした…。すっかり忘れてました!

      当時、評価関数が小さかったので起動時に評価関数ファイルを読み込んでも特に問題とならなかったのですが、それが評価関数が肥大化したことで色々顕在化したわけですね。それで、結局、isreadyで評価関数ファイルを読み込まざるを得なくなって、「これは毎局必ず送られてくるのか?」がUSIプロトコルの仕様としてきちんと書かれていないことが問題となったわけで、そのことを5年前に指摘していたmerom686さんは、凄いですなー。

  1. Stockfish ですが、

    is readyがきたら初期化する。初期化済みフラグを立てて、その後のucinewgameでは初期化しない。

    is readyなしにucinewgameがきたら、初期化済みかチェックして、あわててそこで持ち時間使って初期化する。

    というように実装して、初期化時間を持ち時間消費に含めるかどうかは、呼び出し側のGUI等の判断事項としとけばいいのでは?

    毎局送られるかどうかの保証や定義は不要と思います。
    あった方がいいですが、すでに保証なしで動いている以上は。

    将棋エンジンもそうするべきかは悩みますが。

    • 別にuciやusiに詳しい人ではなく、20年前にプロセス間通信のプログラム書いてたってだけです。

      色んなバージョンが混在する環境で、何とか正常動作させる方向で。

      もちろん、中途半端に動かすと障害の切り分けの難易度が超上がります。
      そういう善解、救済的動作はアンドキュメンテドな場合も多いですし。

      でもこの場合は、そんな複雑な話でもないし、命掛かってもないし、善解動作でいいんじゃないでしょうか。

  2. チェスのGUIの実装を見ると毎局1回だけではなくて、何かしらコマンドを送った後にもisreadyを送ってたりします。

    これが正しいとするならucinewgameで巨大な置換表クリアしていても、その後にisready->readyokでうまく同期がとれてるんじゃないでしょうか。

    • UCIの仕様ページらしきものをみると、
      isreadyは時間がかかる処理のあとGUIがエンジンと同期とったりエンジン生存を確認するのに使う。

      ucinewgameの後はGUIはisready呼んだ方がいい。

      初期局面送られたエンジンはそこから思考を始めていい。
      エンジンはGUIがucinewgame を送ってくると期待するな。GUIはucinewgame 非対応かもしれん。

      とありますね。

      するとUCIでは、isready で初期化したらあかんやん!

      • http://wbec-ridderkerk.nl/html/UCIProtocol.html

        isreadyが送られてくるより先行して初期化スレッド(評価関数のファイルなどの読み込み)は走っていて、その初期化が終わっているかどうかをisreadyに対して返すのが本来の使い方のように読めますね。一種のping的なコマンドだと解釈できます。

        しかしまあ…、isreadyに対してNG(readyng)のような応答を返せないので、結局ここでGUI側はreadyokが来るまで待たされるわけですから、思考エンジン側はisreadyを初期化の起点としても別に構わないような気はしますが。

        ucinewgameが送られてくることを期待してはいけないとは知りませんでしたが、上のドキュメントには確かにそう書いてありますね。

        • isreadyのタイミングで最初に1回だけ評価関数ファイルを読み込むのは問題なさそうですけど、
          毎回置換表クリアすると、UCIでは予期せぬタイミングでクリアされそうですね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です