SSブログ

GPSFISHのビルド [プログラミング]

2chを見てたら、なんでもGPSFISHがボナンザ有料版(6.1.1)に2勝8敗だったという。

で、ビルド方法を書いたサイトがあったので真似してやってみた。

http://www.geocities.jp/shogi_depot/doc/gpsfish_cygwin.htm

GPSFISHは元々Linuxのソフトウェアなので、Windowsでビルドするには骨が折れる。
が、そこはCygwinというLinux環境もどきを作ってくれるソフトウェアを使うことで対応している。

が、完全に互換というわけでもないので、いくつかは修正がいる。

で、基本的に上の通りにやればOKなのだが、いくつかハマりポイントというか、よく知らないとはまるポイントがあったのでまとめておこうと思う。

■ソースコードの取得

http://gps.tanaka.ecc.u-tokyo.ac.jp/gpsshogi/index.php?GPSFish

これは本家のところからダウンロードすればよいのだが、3つのリポジトリからダウンロードする必要がある。
SVN使うのがめんどくさいという人は、Tar.gz形式のアーカイブをダウンロードできるのでそれでダウンロードすれば良い。自分はそうした。

http://gps.tanaka.ecc.u-tokyo.ac.jp/cgi-bin/viewvc.cgi/trunk/osl/
http://gps.tanaka.ecc.u-tokyo.ac.jp/cgi-bin/viewvc.cgi/trunk/gpsshogi/?root=gpsshogi
http://gps.tanaka.ecc.u-tokyo.ac.jp/cgi-bin/viewvc.cgi/branches/gpsfish_dev/?root=gpsfish

全部落としてきて、並列に展開すれば良い。

■Cygwinで必要なもの

散発的に書かれていて、手順通りに進めるといちいちCygwinを起動しないといけなくなる
必要な物は

gcc,make,iconv-dev,libboost-dev,libbz2-dev

あたり。コンパイル時にヘッダファイルが必要な場合は-devなパッケージを選択するのが世の常。

■環境変数

OSL_HOMEをgpsshogiフォルダに設定

とあるが、すでにコンパイル済みGPSFISHをインストールしてある場合、別のフォルダになっていると思うのでそれを変更する必要がある。

■変更パッチ

文字で書かれているとよくわからないのでパッチ化。

diff -r 7c48bab4e7c3 gpsfish_dev/src/Makefile
--- a/gpsfish_dev/src/Makefile	Sat Jul 27 00:31:09 2013 +0900
+++ b/gpsfish_dev/src/Makefile	Sat Jul 27 18:17:23 2013 +0900
@@ -54,8 +54,15 @@
 
 programs : gpsfish
 
-gpsfish: $(OBJS) $(FILE_OSL_ALL)
-	$(CXX) -o $@ $(CXXFLAGS) $(PROFILE_USE) $(LDFLAGS) $(OBJS) $(FILE_OSL_ALL) $(LDLIBS) $(LOADLIBES) -lbz2
+gpsfish: $(OBJS)
+	$(CXX) -o $@ $(CXXFLAGS) $(PROFILE_USE) $(LDFLAGS) $(OBJS) \
+../../osl/release/libosl_search.a ../../osl/release/libosl_board.a \
+-lboost_filesystem-mt.dll -lboost_serialization-mt.dll -lboost_iostreams-mt.dll \
+-lboost_date_time-mt.dll -lboost_system-mt.dll -lboost_thread-mt.dll -lboost_program_options-mt.dll \
+-lpthread -lbz2 -liconv
+
+#gpsfish: $(OBJS) $(FILE_OSL_ALL)
+#	$(CXX) -o $@ $(CXXFLAGS) $(PROFILE_USE) $(LDFLAGS) $(OBJS) $(FILE_OSL_ALL) $(LDLIBS) $(LOADLIBES) -lbz2
 
 gpsfishoneprof: mainone.cc
 	$(CXX) -o $@ $(CXXFLAGS) $(OSL_HOME_FLAGS) $(PROFILE_GENERATE) $(LDFLAGS) $< $(LDLIBS) $(LOADLIBES) -lbz2
diff -r 7c48bab4e7c3 gpsfish_dev/src/search.cpp
--- a/gpsfish_dev/src/search.cpp	Sat Jul 27 00:31:09 2013 +0900
+++ b/gpsfish_dev/src/search.cpp	Sat Jul 27 18:17:23 2013 +0900
@@ -663,12 +663,14 @@
 
   // UCI protol is not clear on allowing sending an empty ponder move, instead
   // it is clear that ponder move is optional. So skip it if empty.
+#if 0
   if (ponderMove != MOVE_NONE)
 #ifdef GPSFISH
     cout << " ponder " << move_to_uci(ponderMove);
 #else
       cout << " ponder " << ponderMove;
 #endif
+#endif
 
   cout << endl;
 
diff -r 7c48bab4e7c3 gpsfish_dev/src/ucioption.cpp
--- a/gpsfish_dev/src/ucioption.cpp	Sat Jul 27 00:31:09 2013 +0900
+++ b/gpsfish_dev/src/ucioption.cpp	Sat Jul 27 18:17:23 2013 +0900
@@ -106,7 +106,7 @@
     mib[1] = HW_USERMEM;
     if (sysctl(mib, 2, &usermem, &len, NULL, 0) == 0
        && len == sizeof(usermem)) {
-      memory = std::min((size_t)2048, usermem/1024/1024/4);
+      memory = std::min((size_t)1024, usermem/1024/1024/4);
     }
   }
 #  elif defined (_WIN32)
@@ -115,7 +115,7 @@
     statex.dwLength = sizeof(statex);
     GlobalMemoryStatusEx(&statex);
     const size_t bytes = statex.ullTotalPhys; // in bytes
-    memory = std::min((size_t)2048, std::max(memory, bytes/1024/1024/4));
+    memory = std::min((size_t)1024, std::max(memory, bytes/1024/1024/4));
   }
 #  else
   {
@@ -124,7 +124,7 @@
     std::ifstream is("/proc/meminfo");
     if (is >> name >> value >> unit
        && name == "MemTotal:" && unit == "kB")
-      memory = std::min((size_t)2048, std::max(memory, value/1024/4));
+      memory = std::min((size_t)1024, std::max(memory, value/1024/4));
   }
 #  endif
   o["Hash"] = UCIOption(memory, 4, 8192);
@@ -145,7 +145,7 @@
   o["Emergency Base Time"] = UCIOption(200, 0, 30000);
   o["Emergency Move Time"] = UCIOption(70, 0, 5000);
 #endif
-  o["Minimum Thinking Time"] = UCIOption(20, 0, 5000);
+  o["Minimum Thinking Time"] = UCIOption(1500, 0, 50000);
 #ifndef GPSFISH
   o["UCI_Chess960"] = UCIOption(false);
   o["UCI_AnalyseMode"] = UCIOption(false);
diff -r 7c48bab4e7c3 osl/lib/misc/iconvConvert.cc
--- a/osl/lib/misc/iconvConvert.cc	Sat Jul 27 00:31:09 2013 +0900
+++ b/osl/lib/misc/iconvConvert.cc	Sat Jul 27 18:17:23 2013 +0900
@@ -73,7 +73,7 @@
   const char * inbuf = src.c_str();
   char outbuf[1024], *outbufptr = outbuf;
   size_t inbytesleft = src.size(), outbytesleft = 1024;
-#if (defined __linux__ || defined __APPLE__)
+#if (defined __linux__ || defined __APPLE__ || defined __CYGWIN__)
   typedef char ** iconv_inbuf_t;
 #else
   typedef const char ** iconv_inbuf_t;
diff -r 7c48bab4e7c3 osl/lib/misc/ncores.cc
--- a/osl/lib/misc/ncores.cc	Sat Jul 27 00:31:09 2013 +0900
+++ b/osl/lib/misc/ncores.cc	Sat Jul 27 18:17:23 2013 +0900
@@ -4,7 +4,7 @@
 #include 
 #include 
 
-#if defined(__linux)
+#if defined(__linux) || defined(__CYGWIN__)
 #   include 
 #elif defined(__APPLE__)
 #   include 
@@ -21,7 +21,7 @@
 ncores() {
   int cpuCount = 1;
 
-#if defined(__linux)
+#if defined(__linux) || defined(__CYGWIN__)
   cpuCount = sysconf(_SC_NPROCESSORS_ONLN);
 #elif defined(__APPLE__)
   kern_return_t kr;
diff -r 7c48bab4e7c3 osl/makefile.conf
--- a/osl/makefile.conf	Sat Jul 27 00:31:09 2013 +0900
+++ b/osl/makefile.conf	Sat Jul 27 18:17:23 2013 +0900
@@ -27,7 +27,7 @@
 USE_GCH ?= no
 USE_BOOST_POOL_ALLOCATOR ?= 0
 USE_TBB_SCALABLE_ALLOCATOR ?= 0
-USE_TCMALLOC ?= 1
+USE_TCMALLOC ?= 0
 TCMALLOC ?= google-perftools-1.7
 USE_TBB ?= 0
 GTEST ?= gtest-1.1.0


あとはmakeを4回ぐらいやればコンパイルできる。
ここらへんは本家と同じはず。

■Cygwin的な準備

Cygwin環境だとDLLのパスを通す的な何かがいる
やりかたをまとめたサイトの人のときよりboostのバージョンがあがっていたので以下の様な感じ。

-rw- 51214 2013-05-09 08:10 cygboost_date_time-mt-1_53.dll
-rw- 79374 2013-05-09 08:10 cygboost_filesystem-mt-1_53.dll
-rw- 87566 2013-05-09 08:10 cygboost_iostreams-mt-1_53.dll
-rw- 384014 2013-05-09 08:10 cygboost_program_options-mt-1_53.dll
-rw- 430606 2013-05-09 08:10 cygboost_serialization-mt-1_53.dll
-rw- 16398 2013-05-09 08:10 cygboost_system-mt-1_53.dll
-rw- 83982 2013-05-09 08:10 cygboost_thread-mt-1_53.dll
-rw- 62990 2011-05-22 04:17 cygbz2-1.dll
-rw- 105501 2013-06-16 13:23 cyggcc_s-1.dll
-rw- 899101 2013-06-16 13:45 cygstdc++-6.dll
-rw- 3113058 2013-07-23 00:07 cygwin1.dll
-rw- 74269 2013-05-10 06:21 cygz.dll
-rwx 10676626 2013-07-27 01:32 gpsfish.exe*

これだけあればgpsfishが動く。

gpsfishができたら動かしてusiとコマンドをうつと、何やらいろいろでてくればOK。
ここでクラッシュするようだと何か問題がある。

■コンパイルしてみてわかったこと

本題はここなんだが、明確な優位性はなかった。というか逆に弱くなってるんじゃとすら思う。

・読みの速度が2割ほど落ちている
 これはgccでコンパイルした弊害だと思うが、正直分からない。プロファイルを利用した最適化をしないと速くならないんじゃないかと思う。あとMakefileにiccみたいなことが書いてあったので、高速化したい人必須のインテルコンパイラを使っているためだと思われる。

・何か変わったか
 あまり変わった感じがしないが、十数手目以降の読み筋が逐次報告されるようになっている。これはクラスタリング化する際に情報を伝えるための工夫だろうか。

・メモリの使用量
 ちょうどパッチを当てた当たりにかいてあったが、最大2GBか、トータルメモリの4分の1ぐらいなので、8GB積んだPCでは2GB使うだろうが、自分の場合は3.6GBぐらいなので900MBぐらい。実際には600MBぐらいしか使われていない模様。

・マルチスレッド
 2chではGPSは1コアで動くみたいなことを言われているが、GPSはCPUの個数を調べて勝手にマルチスレッドで動くのでCPUが多ければ多いほど早くなる。ただし、悪名高きHyperthreadingなCPUを搭載している場合に、スレッドが待たされる場合が増えるので逆に悪くなる場合がある模様。コンパイルオプションでSIMD最適化
するようにしたらHTでも遅くならない気はするが、持ってないのでよくわからない。

・GPSが使うバイナリについて

GPSは3つのバイナリを使う

-rw- 60 2013-07-27 01:04 eval.bin
-rw- 74 2013-07-27 01:04 joseki.dat
-rw- 68 2013-07-27 01:04 progress.txt

dataフォルダに入ってるこれらを参照するが、サイズを見てもらうと分かる通り、Cygwinの環境で作られる仮想シンボリックリンクエミュレートファイルになっている。中身を見るとパスがかいてある。

なのでOSL_HOMEを変えると、配布されているGPSがクラッシュして動かなくなる弊害がある。

単にこの場所に参照元のファイルをコピーすればいいだけだと思うが、まだやっていない。
なお参照元のファイルはgpsshogi/dataにある。

さらにjoseki.datはjoseki-wide.datのほうを使っている模様。

■で、強いのか

試しに先手Blunderの2011年バージョン,後手GPSFISHで30秒、先読みなしで戦わせた
PCが1台であるので先読みは無し。

結果はGPS惨敗。寄らない無理攻めと筋の悪い金銀打ちがたたって大敗だったのだが、読み筋的には「いける」と思っていたらしく、大駒4枚取られてやっと、「やっぱわるかったか」みたいな評価になった。

棋譜を残すのを忘れていた。
後手番のGPSがある局面で8八金打ちをしたのだが、これが大悪手もいいところで、プロなら指さない手だと思われる。そこから寄るわけでもないのに龍を切るとかひどい手順のオンパレードだった。

むしろBlunderのほうが正しかったといえる。

GPSの場合、クラスタリングで馬鹿みたいに読めばアホな手を指さないだろうというスタンスなので、単一PCで十数手ぐらいしか読めないのではあまり意味が無い。

また12手ぐらいなら10秒ぐらいで読み切り、そこから、1手増やすごとに馬鹿みたいに読む量が増えて遅くなるので、30秒でも15秒でもあまり変わらない感じがする。逆に10秒を5秒にすると明らかな悪手がある。

対局させてみるとBlunderはプライマリとして、怪しいけど複数の手順を考慮とか、要らない手は思い切って読まないとか、一目の手順は考えないとか工夫が見られる。

一方でGPSはセカンダリなので、馬鹿正直に毎回30秒考えて指すようにしかなっていない。

まあ、結局のところ、ビルドするより配布されているのを使ったほうが楽だし十分であるという悲しい結果であった。

ただ、定石ファイルがアップデートされているので、むしろファイル挿し替えるだけでもいいのではないかとも思うがよくわからない。対戦に不向きと書いてあるのはそういうことなんだろう。

nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。