今年の選手権の話でも

第29回世界コンピュータ将棋選手権にエントリーしました。

恥ずかしながら昨年王者第一シードで御座います。

 

www.apply.computer-shogi.org

 

一昨年が電王トーナメント準優勝。

昨年が世界選手権優勝。

どちらも初参加ですが,相当雰囲気が違います。

電王トーナメントのときはそれこそ出張ついでで目立たないように逃げてたのですが,昨年の選手権ではチーム体制で一応そこそこ勝つことを目標にして参加しました。

まぁ,個人は気楽ですが色々と機材管理から飲食物調達など大変なのでサポート要員は居る方が楽ですね。荷物は電王トーナメントのトロフィーとかその他出張の邪魔なので翌日には宅配便で自宅に送ったくらいです。選手権の時は両手に紙袋とかわんさと下げて新幹線に乗りました。電王トーナメント唯一の切れ負けはインタビューの最中でしたし,予備のUSBメモリは自宅玄関で待機してましたし,耳栓はスタッフの方に買いに行って頂きました。そういうことでチーム体制が色々安心安全です。ただ,チーム体制にすればそれなりにチームの方向性を決めておく必要があるので,昨年の目標は予選通過ってお題目で意志統一してました。作業分野的に丁度手分けできたのは特に計算してやったことじゃないです。意外かもしれませんがw

 

で,今年はどうよってことですわ。

酒の肴的には「連覇」なんですが,そんなことは少ししか思ってません。

一応電王トーナメントのときにできなかった焼肉打上をあわよくば実現したいと思ってます。とはいえ優勝した翌年予選落ちのelmoの例がありますので気を引き締めて準備しときたいですね。ちなみに実は未だelmoとの対局がありません。今年こそお手合わせ願いたいです。

まぁ,なんやかんや考えてもルール的にも一次予選免除くらいの利点しかないので普通の参加者として昨年同様に参ります。(前日入りの必要がないので会場設営にはいくかどうかは未定)

 

具体的な準備としてはネタ的に考えていたのを順番に実装してテストしてる最中ですが,今のところノーヒットです。特に探索部の改造の是非は非常に難しいです。唯一PythonをGo言語に書き換えた部分は確実に高速化してるくらいでしょうか。複雑な制御を追加しても遅延等問題なさそうです。他当たりそうなアイデアはあるのですが実装力が追い付かない感じで情けない限りです。個人的な得意分野としてマルチコア・クラスタなどは上手に使っていきたいと思います。

 

気になるのは他チームの動向です。個人的に気にしているのが昨年のうちの戦略を他チームがどれくらい取り込んでくるかってことです。コム将の間では真似されるのが誇りでありますので色々と真似していただければ幸いです。ただ,MultiPonder同士が当たるとどんなことになるのか手元でもリソース不足で実験できていません。

それにディープラーニング勢ですね。最右翼はもちろんdlshogiの山岡さんですが,フランスのRemiさんがガチ宣言入ってますし,保木先生が何故か新人扱いでディープラーニング勢の闘気が漂うトリオで参戦されています。池さんも何故か新人枠ですw

忘れていけないのが,やね師匠ですね。新人賞候補とか卑怯な感じしかしません。Yorkieの石田さんもエントリーされてますのでお会いできるのが楽しみです。大将軍には唯一負け越してますので今年中に五分に戻したいです。平岡さんも開発言語にRustしか書いてないのでお会いした時には是非話を聞きたいと思ってます。う~む,個別に書き出すときりがないですねwww

 

夕飯の準備もあるので今日はこの辺で 

シングルスレッド性能が速いのが欲しいときがある

Pythonで色々処理してると多コアが全く役に立たないことが多い。

自前で用意したシミュレーション系ツールも並列化してないと同様。

つまりシングルスレッド性能でしか生かされない。

 

そういうこともあろうかと,Skylake世代でKプロセッサを仕入れてたんだけど,これがシングルスレッド時のターボブーストで4.2GHz。

近頃は9900Kとか8086Kとかが5GHzで動くらしい。

 

ふと手持ちのモバイル機器を確認してみたら8550Uが4GHzで8750Hが4.1GHzだそうな。

嗚呼,シングルスレッド性能がモバイルに追いつかれてしまった。

 

コム将で例えると山岡さんのpython-dlshogiが結構pythonに足を引っ張られてて,GPUは1050クラスでも1080クラスでもさほど影響ないが,シングルスレッド性能に結構依存しててクロック比に近いnpsが出る。

つまり,ウチではDELLのG3が8750Hの4.1GHzで最強。

 

5GHzのやつが急に一個欲しくなったって話。

合法手の話

その昔,"指し手生成祭"という祭があったようです。(詳しくはググってください。)

将棋の局面で反則にならない手が何種類あるかってのをリストにする速度を競ってたそうです。私は先日Go言語で組んだのだとざっくり200kくらいが最高値でした。たぶん一桁負けてますね。

これが何に有効かというと速度の問題ももちろんですが,探索の枝の生成になります。コンピュータ将棋の本質は木探索なので枝の数とかその性質とかが重要ですね。

 

  

枝の数が気になるってことで,python-shogiでざっと棋譜読んで数えさせてみました。

こういうときはカジュアルなライブラリが便利です。

 

bleu48.hatenablog.com

 

まぁ,こんな感じで簡単に数えられますね。

kifフォルダ以下のkifファイルを全部読んで全局面の合法手生成をしますのでちょっと時間かかります。

 

import shogi.KIF
import os

def find_all_files(directory):
for root, dirs, files in os.walk(directory):
  for file in files:
    yield os.path.join(root, file)
num_board=0
sum_moves=0
for filepath in find_all_files("kif"):
  kif = shogi.KIF.Parser.parse_file(filepath)[0]
  board = shogi.Board()
  for move in kif['moves']:
    board.push_usi(move)
    moves=[]
    for m in board.legal_moves:
      moves.append(m)
    sum_moves += len(moves)
    num_board += 1
print("局面数",num_board,"総合法手数",sum_moves,"局面当たりの平均合法手数",sum_moves/num_board)

  

沢山やると遅いので,うちの選手権棋譜24局だけですが

局面数 3920 総合法手数 387904 局面当たりの平均合法手数 98.95510204081633

ってことで,割と手が広いようです。 

皆さんも手持ちの棋譜で調べてみてください。

Apery調査の件

まず,遊び道具を提供下さった平岡さんに感謝します。

思えば三年前になるんですね。教師データの作成依頼のツイートが流れてきたのが,そもそも私がコンピュータ将棋に触れるきっかけでした。

ダイアリーの方からインポートされた記事があるのでリンク残しておきます。

100万局面ずつの生成ってことで,たまたま他の数値解析のベンチマークを取っていた時期でもあったのでありったけの計測を行った序でに,恐らく累計1億近くお送りさせて頂いたと思います。

 

bleu48.hatenablog.com

 

ということなので,この年から電王トーナメントを見ました。

古い話は去年くらいから調べさせていただいたので可能な限りついていきます。

 

話は変わって,5月にやった以下の件です。

bleu48.hatenablog.com

 

うちの学生がコンピュータ将棋に関する研究をしたいというので色々と調べてもらったのですが,結果はどうもAperyがQhapaqやTNKを上回るわけがないという統計データしか出ませんでした。他サイトのレーディング計測の通りなので,詳細はネット上では省きます。

 

で,最後に気になったのがアレです。

決勝の朝,笑顔で御説明頂いたってやつです。

github.com

 

確かにびっくりしました。前日予選の棋譜引用の定跡ですからね。

それは「Aperyの指し手」なのかなぁとも思ったわけです。

ただ,これが最上位のリスペクトだと気づいたのは随分後になります。

優勝前に前チャンピオンelmoや電王TNKと並べて頂いてたのでホント光栄です。

 

対戦相手の設定や都合などもあると思いますが,具体的に予選棋譜などと見比べて一応私なりの結論がこれですね。

ですので選手権3位の理由の一つが序盤定跡。

これ入れないとAperyの序盤甘いよね。

レーティングは計測値が信頼できるとしておきます。

チェスのエンドゲームの話

囲碁とチェスの終盤はシンプルだって話は何回かしてる。

コンピュータ将棋の調べもの(主に自分用メモ) - 48's diary

将棋とチェスの違い(Stockfishを参考に探索部を強化する際の注意点) - 48's diary

 

シンプルって言っても程度があって五目並べやオセロに比べたらちょっと大変。

囲碁でも日本ルールと中国ルールで勘違いとかして大逆転があったりするくらい。

コンピュータ的には競技母体の関係か中国ルールが主流らしい。日本ルールはコンピュータ的実装がちょいとややこしいらしい。私はそもそも囲碁に詳しくないのでこれくらいの知識。

 

チェスは残り駒が減る競技で,残り6個になったら全組み合わせが既に探索が終わっててそれを参照すれば最善解が得られるようになっている。

いや,「いた」ってのが正しい。

 

昨日知ったんだが去年の夏からこれが,7個になってた。

384 threads (8x Intel Xeon Platinum 8168)を5か月ぶん回して出来た,参照すべきデータベースのサイズが18.4TBだそうな。

lichess.org

 

18.4TBのストレージがなくてもWebAPIを叩けば答えを返してくれるらしい。

 

github.com

 

これ,人間同士でも参照するんだろうか。

将棋だと持将棋みたいなもんでしょ。

Go言語で配列のメモリイメージをそのままファイルから読む

  

その後解決したのでメモっておく。

参考にしたのは以下のところ。

 

qiita.com

 

要点だけ引っ張ったコードが以下になる。

KPP := make([]int16, 81*1548*1548*2)
file, err := os.Open("eval/KPP_synthesized.bin")
p_kpp := (*[2 * 81 * 1548 * 1548 * 2]byte)(unsafe.Pointer(&KPP[0]))[:]
file.Read(p_kpp)

 

int16のスライスの先頭アドレスをバイト列のポインタにキャストしてあげている。

結果はエンディアン依存することになるけど,そもそもbinary.Readが重い理由が全データをエンディアン変換をしてるからなんだよね。

使いまわさない前提でローカル運用するコードだから許して下さい。

 

Go言語雑感

Go言語について入門書のチュートリアルくらいはちょっとやってたんだけど,実用でどのくらい使えるかテストしてみました。

ターゲットは例の如く将棋ですね。

どっかの移植でも面白くないので,池さんの参考書やらオープンソースの他のソフトを適当に読み散らかしながら自分なりの実装をしてみました。

特に速度や互換性などには特に考えない習作レベルです。bitboard使ってないです。

そいやpythonでもやったんですがね。

 

昨年末,盤の設計から局面表示,合法手生成辺りを2日くらいで作ってました。ちょっとした合間を見つけてUSIプロトコルに対応させてランダム対戦まで昨年内にできてました。

 

そして年明けの昨日から探索部を作成。

シンプルなαβ法を実装した段階ではシングルスレッドで200knpsくらい出てました。やねうら王には随分負けているがGo言語実装ってのを考えたら健闘してるかなぁって印象。

 

評価値を駒得以外にKPPっぽいものを実装したら,探索速度が桁違いに落ちました。それでも,LesserKaiに勝てるようになりました。pythonでは届かなかった領域なので,ちょっと満足。

 

 

5手爆弾にハマるのでまだまだですね。コンピュータ将棋の歴史を学んでいる気分です。

  

で,色々便利だと思ってGo言語やってみたけど,メモリ管理など低レイヤーの部分で意外に使いにくいことも見つかってきた上にC++でスクラッチの方が将来性あるしよかったんじゃないかとも思い始めてきて今後の運用は微妙なところです。

ちょうど気づいたのはGPS将棋がいつのまにかPerlからGo言語になってたんですね。うちもそれを知らずに同じようなことを考えていたのですが,う~む。どうしようかしら。他言語でいうとRust勢とかどんな感じなんでしょう?

#なんか書き散らしてたら考えがまとまるかと思ったけど全然ダメでした

 ---

追記:

翌日思い付きで並列計算化してみました。古いマシンだと合法手生成部分の並列化は若干有効でしたが,それ以外の評価値計算などは何しても遅くなる一方でした。やはり探索スレッド単位で並列化するのが望ましいようですね。誰もやらないわけですw

---

さらに追記:

numpy.fromfileみたいな配列のバイナリイメージをそのまま読み込むような機能を探してます。それとそれらを比較的簡単な演算するんですが,ベクトル・行列演算が演算子オーバーロードを禁じてるために簡素な表記ができないなぁと愚痴ってます。数値計算向きじゃないのですねぇ。